您好,登錄后才能下訂單哦!
小編給大家分享一下微前端架構的示例分析,相信大部分人都還不怎么了解,因此分享這篇文章給大家參考一下,希望大家閱讀完這篇文章后大有收獲,下面讓我們一起去了解一下吧!
而提到微前端就離不開微服務,大家對微服務都比較熟悉了,微服務允許后端體系結構通過松散耦合的代碼庫進行擴展,每個代碼庫負責自己的業務邏輯,并公開一個API,每個API均可獨立部署,并且各自由不同的團隊擁有和維護。
前端架構經歷了從單體,到前后端分離,再到微服務,最終發展到現在的微前端的過程如下圖所示:
微前端的思路是把微服務的架構引入到前端,其核心都是要能夠以業務為單元構建端到端的垂直架構,使得單個的團隊能夠獨立自主的進行相關的開發,同時又具備相當的靈活性,按需求來組成交付應用。
“微前端”一詞最早于2016年底在ThoughtWorks 技術雷達中提出的。它將微服務的概念擴展到了前端世界。當前的趨勢是構建一個功能強大且功能強大的瀏覽器應用程序(也稱為單頁應用程序),該應用程序位于微服務架構之上。隨著時間的流逝,通常由一個單獨的團隊開發的前端層會不斷增長,并且變得更加難以維護。
微前端背后的想法是將網站或Web應用程序視為由獨立團隊擁有的功能的組合。每個團隊都有自己關心和專長的不同業務或任務領域。一個團隊是跨職能的,并且從數據庫到用戶界面,端到端地開發其功能。
但是,這個想法并不新鮮。它與“單體系統”概念有很多共同點。在過去,類似的方法被稱為“垂直系統的前端集成”。但是微前端顯然是一個更友好,更輕巧的術語。
在微服務的架構中,后臺的服務已經按照業務進行了分離,而前端仍然是一個單體構建,通過網關來調用不同的后臺服務。這個微服務的思路是相違背的,這也就造成了你的后端團隊是按照業務分割的,但是前端團隊仍然是一個整體。微前端可以有效地改進這一點。
微前端的核心思路其實是遠程應用程序,包含組件/模塊/包的運行時加載。
如上圖,對于用戶而言,訪問的是一個微前端的容器(container),容器加載運行在遠程服務上的應用,把這些遠程應用作為組件/模塊/包在本地瀏覽器中加載。
組件是底層UI庫的構建單元
模塊是相應運行時的構建單元
包是依賴性解析器的構建單元
微前端是所提出的應用程序的構建塊
在前面我們看到的微前端之前的架構,所有的前端還是一個單體,前端團隊會依賴所有的服務或者后臺的API,前端開發會成為整個系統的瓶頸。使用微前端,就是要讓前端業務從水平分層變為垂直應用的一部分,進入業務團隊,剝離耦合。
那么微前端有什么好處,為什么要采用微前端架構呢?
各個團隊獨立開發,相互不影響,獨立開發、獨立部署,微應用倉庫獨立,前后端可獨立開發,部署完成后主框架自動完成同步更新
增量升級,在面對各種復雜場景時,通常很難對一個已經存在的系統做全量的技術棧升級或重構,而微前端是一種非常好的實施漸進式重構的手段和策略。因為是運行時加載,可以在沒有重建的情況下添加,刪除或替換前端的各個部分。
不受技術影響,每個團隊都應該能夠選擇和升級其技術棧,而無需與其他團隊進行協調。也就是說A應用可以用React,而B應用使用Vue,大家可以通過同一個微前端來加載
獨立運行時,每個微應用之間狀態隔離,運行時狀態不共享。隔離團隊代碼,即使所有團隊都使用相同的框架,也不要共享運行時。構建自包含的獨立應用程序。不要依賴共享狀態或全局變量。
建立團隊命名空間,對于CSS,事件,本地存儲和Cookies,可以避免沖突并闡明所有權。
因此,微前端和微服務的本質都是關于去耦合。而只有當應用程序達到一定規模時,這才開始變得更有意義。
微前端不是一個庫,是一種前端架構的設計思路,要實現微前端,本質上就是在運行時遠程加載應用。
實現微前端,有幾個思路,從構建的角度來看有兩種,編譯時構建微前端和運行時構建微前端:
編譯時微前端,通常將第三方庫中的組件作為包,在構建時引入依賴。這種實現引入新的微前端需要重新編譯,不夠靈活。編譯時的微前端可以通過Web Components,Monorepo等方式來實現。其中Monorepo非常流行,常見的工具有nx,rush,lerna等。
運行時微前端,是一次加載或通過延遲加載按需動態將微型前端注入到容器應用程序中時。當引入新的微前端的時候,不需要構建,可以動態在代碼中定義加載。我眼中的微前端更多是指這種運行時加載的微前端,因為獨立構建,部署和測試是我們對于“微”的定義。
從前后端責任分層來看,可以從前端或者后端來實現。
通過客戶端框架來實現
微前端通常由客戶端工具來支持實現(聽上去好有道理),有許多支持客戶端開發微前端的實現工具,包括:Piral,Open Components,qiankun,Luigi,Frint.js等。其中qiankun是螞蟻金服開發的。
在客戶端還可以通過輔助庫的方式來實現,輔助庫可以為共享依賴項,路由事件或不同的微前端及其生命周期來提供一些基礎架構。
下面的一個示例是通過諸如導入映射或打包特定塊等機制處理共享依賴關系。
相關的工具有Webpack5 Module Federation,Siteless,Single SPA,Postal.js等
微前端并非只能在客戶端來實現,類似于服務端渲染,同樣可以通過服務端來實現。
服務端微前端的支持工具有:Mosaic,PuzzleJs,Podium,Micromono等。
好了,說了這么多我相信你是一臉懵逼的,到底怎么實現的?我們拋開架構不說,來看看到底如何實現吧。
iframes是可以在html中嵌入另一個HTML。下面就是用iframe實現微前端的一個例子:
<!DOCTYPE html> <html> <body> <iframe src="http://localhost:3006" width="600" height="900"> <p>Your browser does not support iframes.</p> </iframe> <iframe src="http://localhost:3007" width="600" height="900"> <p>Your browser does not support iframes.</p> </iframe> </body> </html>
如果不考慮體驗問題,iframe 幾乎是最完美的微前端解決方案了。iframe 提供了瀏覽器原生的隔離方案,不論是樣式隔離、js 隔離這類問題統統都能被完美解決。但它的最大問題也在于他的隔離性無法被突破,導致應用間上下文無法被共享,隨之帶來的開發體驗、產品體驗的問題。這里的主要問題包括:
url 不同步。瀏覽器刷新 iframe url 狀態丟失、后退前進按鈕無法使用。
UI 不同步,DOM 結構不共享。
全局上下文完全隔離,內存變量不共享。
慢。每次子應用進入都需要次瀏覽器上下文的重建、資源重新加載。
所以雖然使用iframe可以實現遠程加載的效果,但是因為這些限制,很少會有應用會使用。
利用Ngix路由,我們可以把不同的請求路由到不同的微前端的應用。
例如Nginx的路由能力,在前端可以動態請求不同的后端應用,而每一個后端應用獨立運行,前端可以把這些不同的后端應用加載,編排在一起。下面的代碼是一個Nginx的配置,customers/users/admins分別表示了三個不同的應用,前端通過路由來加載位于不同服務的后端應用。
worker_processes 4; events { worker_connections 1024; } http { server { listen 80; root /usr/share/nginx/html; include /etc/nginx/mime.types; location /app1 { try_files $uri app1/index.html; } location /app2 { try_files $uri app2/index.html; } location /app3 { try_files $uri app3/index.html; } } }
無論你采用哪一種的微前端架構,Nginx方向代理或者其它的API網關的解決方案都能夠提供方便靈活的后端路由功能。但是通過這種方式,需要定義一個通用可擴展的路由規則,否則當引入新的應用的時候,還需要修改Nginx的路由配置,那就很不方便了。
Webpack5 的Module Federation是一個令人興奮的革新,它能夠很方便的支持微前端的構建。模塊聯合允許JavaScript應用程序從另一個應用程序動態加載代碼,并在此過程中能共享依賴關系。如果使用Module Federation的應用程序不具有聯合代碼所需的依賴關系,則Webpack將從該聯合構建源中下載缺少的依賴關系。
在Module Federation的上下文中,啟動代碼是一種將運行時代碼附加到遠程容器啟動序列的實施策略。這真的很有用,因為通過Hook無法訪問ModuleFederation及其運行時,無法對其進行擴展或添加一行代碼,這些代碼可以像動態設置遠程容器的公共路徑那樣進行操作。這在普通的webpack應用程序中是微不足道的,但是在一個無法訪問的自定義運行時容器中卻很難做到,該容器為模塊聯合遠程編排提供了動力。簡單來說,Module Federation注入一段運行時的代碼來負責加載和編排遠程的應用代碼,并能夠管理和加載遠程應用的依賴。
下面是一個對應的例子:
module.exports = { mode: 'development', devServer: { port: 8080, }, plugins: [ new ModuleFederationPlugin({ name: 'container', remotes: { microFrontEnd1: 'microFrontEnd1@http://localhost:8081/remoteEntry.js', microFrontEnd2: 'microFrontEnd2@http://localhost:8082/remoteEntry.js', }, }) ] };
上面的代碼是微前端的容器端的配置,容器負責加載其它遠程應用的代碼。這個例子里,它加載了兩個遠程應用。
module.exports = { mode: 'development', devServer: { port: 8081, }, plugins: [ new ModuleFederationPlugin({ name: 'microFrontEnd1', filename: 'remoteEntry.js', exposes: { './MicroFrontEnd1Index': './src/index', }, }), ] };
每一個微前端的Webpack配置如上。
利用ModuleFederationPlugin,remote可以用來加載遠端的應用,而Expose可以把自己的組件暴露為遠端組件。
在container中,只需要調用以下的代碼來加載遠端組件。
import 'microFrontEnd1/MicroFrontEnd1Index'; import 'microFrontEnd2/MicroFrontEnd2Index';
Module Federation的加載過程如上圖所示:
鴻蒙官方戰略合作共建——HarmonyOS技術社區
localhost 加載index.html
main.js 是Module Federation的核心的編排代碼,負責加載遠程組件。
remoteEntry.js 是Module Federation暴露的遠程組件的代碼
src_ 是打包后的代碼,其中 bootstrap_js是容器側的代碼,index_js是微前端側的代碼。
Module Federation實現了類似動態鏈接庫的能力,可以在運行時加載遠程代碼,遠程代碼本質上是一個加載在window上的全局變量,Module Federation可以幫助解決依賴的問題。Javascrip作為上古語言,沒有提供依賴管理,導致留給各路大神各種發揮的空間。
Module Federation的缺點就是依賴Webpack 5,包直接掛載為全局變量。
EMP微前端是基于Module Federation的微前端解決方案。
單頁面應用是當今為Web應用的主流,區別于傳統的多頁面應用,整個SPA只有一個頁面,其內容都是通過Javascript的功能來加載。
SPA是一個Web應用程序,僅包含一個HTML頁面。提供動態更新,它允許在不刷新頁面的情況下與頁面進行交互。利用單頁應用程序,可以顯著降低服務器負載并提高加載速度,從而獲得更好的用戶體驗,因為SPA僅在先前加載整個頁面時才按需導入數據。
除了開發復雜,對于SEO不友好,但頁面應用的最大技術缺陷是URL不適合共享,因為SPA只有一個地址。
single-spa是一個框架,用于將前端應用程序中的多個JavaScript微前端組合在一起。
使用single-spa構建前端可以帶來很多好處,例如:
在同一頁面上使用多個框架而無需刷新頁面(React,AngularJS,Angular,Embe)
獨立部署微前端
使用新框架編寫代碼,而無需重寫現有應用程序
延遲加載代碼可縮短初始加載時間
single-spa應用程序包含以下內容:
single-spa根配置,用于呈現HTML頁面和注冊應用程序的JavaScript。每個應用程序都注冊了以下三項內容:name,加載應用程序代碼的函數,確定應用程序何時處于活動狀態/非活動狀態的函數,
打包成模塊的單頁應用程序的應用程序。每個應用程序必須知道如何從DOM引導,安裝和卸載自身。傳統SPA和Single-SPA應用程序之間的主要區別在于,它們必須能夠與其他應用程序共存,因為它們各自沒有自己的HTML頁面。例如,React或Angular SPA應用程序。處于活動狀態時,他們可以偵聽url路由事件并將內容放在DOM上。處于不活動狀態時,它們不偵聽url路由事件,并且已從DOM中完全刪除。
Single-SPA注冊的應用程序擁有普通SPA所具有的所有功能,只是它沒有HTML頁面。SPA包含許多已注冊的應用程序,每個應用程序都有其自己的框架。已注冊的應用程序具有其自己的客戶端路由和它們自己的框架/庫。它們呈現自己的HTML,并且在安裝時有完全的自由去做他們想做的任何事情。掛載的概念是指已注冊的應用程序是否正在將內容放在DOM上。決定是否掛載已注冊應用程序的是其活動功能。每當未掛載已注冊的應用程序時,它都應保持完全休眠狀態直到掛載。
Single SPA的樣例代碼如下:
import React from "react"; import ReactDOM from "react-dom"; import singleSpaReact from "single-spa-react"; import Root from "./root.component"; const lifecycles = singleSpaReact({ React, ReactDOM, rootComponent: Root, errorBoundary(err, info, props) { // Customize the root error boundary for your microfrontend here. return null; }, }); export const { bootstrap, mount, unmount } = lifecycles;
Single SPA的微前端是純的JS組件,不包含HTML,需要通過容器來加載。
在容器側,需要通過Import Map或者Webpack來定義遠程組件,并注冊遠程應用。
{ "imports": { "@naughty/root-config": "//localhost:9000/naughty-root-config.js", "@naughty/app": "//localhost:8500/naughty-app.js", "react": "https://cdn.jsdelivr.net/npm/react@16.13.1/umd/react.production.min.js", "react-dom": "https://cdn.jsdelivr.net/npm/react-dom@16.13.1/umd/react-dom.production.min.js" } }
容器側的HTML文件使用import map來定義遠程依賴,其中root-config是編排代碼,負責遠程應用的注冊和加載。同時需要定義所有共享的依賴,這里例子中是react和react-dom
import { registerApplication, start } from "single-spa"; registerApplication({ name: "@single-spa/welcome", app: () => System.import( "https://unpkg.com/single-spa-welcome/dist/single-spa-welcome.js" ), activeWhen: ["/welcome"], }); registerApplication( '@naughty/app', () => System.import('@naughty/app'), location => location.pathname.startsWith('/app') ); start({ urlRerouteOnly: true, });
在root-config中,我們注冊了兩個遠程應用,使用不同的url來加載。/welcome會加載welcome應用,而/app會加載我們的app應用。
Single SPA的核心是利用不同的URL路由來加載遠程組件,它可以和Webpack(打包時構建依賴)或者Import Map(運行時使用瀏覽器導入依賴)一起工作。注意,不要在你的微前端中混用兩種依賴機制。
Single SPA還提供一個layout 引擎,可以幫助你快速的構建微前端。
相比Module Federation,Single SPA的代碼和生命周期的管理更清楚,提供清晰的接口,缺點是共享的依賴需要手工通過import map來管理。
要做一個好的微前端因為受限于瀏覽器和JS的一些特性,并不容易。除了我們今天分享的內容,還面臨著諸多的挑戰:如何解決css/js的沖突,使得組件和應用完全隔離;如何解決不同應用間的通信;如何處理路由;如何保證UI風格的統一等等。
講了這么多的優點和實現,那么微前端是不是解決前端開發問題的銀彈呢?當然不是。所有的架構都是取舍和權衡,這個世界上并不存在銀彈,微前端架構和微服務一樣也存在他的弊端,單體架構未必就差。
1. 微前端的構建通常比較復雜,從工具,打包,到部署,微前端都是更為復雜的存在,天下沒有免費的午餐,對于小型項目,它的成本太高。
2. 每個團隊可以使用不同的框架,這個聽上去很美,但是實際操作起來,除了要支持歷史遺留的應用,它的意義不大。同時也為帶來體驗上的問題。可以遠程加載不同的框架代碼是一回事,把它們都用好是另一回事。
3. 性能上來看,如果優化得不好微前端的性能可能會存在問題,至少微前端框架是額外的一層加載。如果不同的微前端使用了不同的框架,那么每一個框架都需要額外的加載。
微前端架構還在發展之中,本文提到的iframe/nginx/module federation/single-spa只是諸多解決方案中的一小部分,前端的發展變化和生態系統實在是豐富,其他的方案諸如umd/乾坤,Piral,open comonent等等。當使用你也可以選擇標準的Web Component或者ES Modules來構建微前端,但是這些標準的瀏覽器支持不是特別好,這個是前端開發永遠的痛。
以上是“微前端架構的示例分析”這篇文章的所有內容,感謝各位的閱讀!相信大家都有了一定的了解,希望分享的內容對大家有所幫助,如果還想學習更多知識,歡迎關注億速云行業資訊頻道!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。