微前端
一、微前端
是一種類似于微服務的架構,它將微服務的理念應用于瀏覽器端。
微服務是面向服務架構(SOA)的一種變體,把應用程序設計成一系列松耦合的細粒度服務,并通過輕量級的通信協議組織起來具體地,將應用構建成一組小型服務。
這些服務都能夠獨立部署、獨立擴展,每個服務都具有穩固的模塊邊界,甚至允許使用不同的編程語言來編寫不同服務,也可以由不同的團隊來管理。
1、將單頁面前端應用由單一的單體應用轉變為多個小型前端應用聚合為一的應用。
2、各個前端應用還可以獨立開發、獨立部署。
3、可以在共享組件的同時進行并行開發——這些組件可以通過 NPM 或者 Git Tag、Git Submodule 來管理。
1、特點
- 代碼庫更小,更內聚、可維護性更高
- 松耦合、自治的團隊可擴展性更好
- 漸進地升級、更新甚至重寫部分前端功能成為了可能
- 獨立部署
2、實現方案
2.1 實現的幾種方式
-
路由分發
- 通過路由將不同的業務分發到不同的、獨立前端應用上。
- 可以通過 HTTP 服務器的反向代理來實現,又或者是應用框架自帶的路由來解決。
- 采用最多、最容易實現的 “微前端” 方案。
- 它適用于以下場景:
- 不同技術棧之間差異比較大,難以兼容、遷移、改造
- 項目不想花費大量的時間在這個系統的改造上
- 現有的系統在未來將會被取代
- 系統功能已經很完善,基本不會有新需求
-
iFrame
- 將另一個HTML頁面嵌入到當前頁面中。
-
應用微服務化
- 每個前端應用一個獨立的服務化前端應用,并配套一套統一的應用管理和啟動機制,諸如微前端框架 Single-SPA 或者 mooa
-
微件化
- 對構建系統的 hack,使不同的前端應用可以使用同一套依賴。它在應用微服務化的基本上,改進了重復加載依賴文件的問題。
-
微應用化
- (組合式集成),即通過軟件工程的方式,在開發環境對單體應用進行拆分,在構建環境將應用組合在一起構建成一個應用。
-
純 Web Components
-
結合 Web Components

2.2 思考
1. 多個 Bundle 如何集成?
2. 子應用之間怎樣隔離影響?
3. 公共資源如何復用?
4. 子應用間怎樣通信?
5. 如何測試?
2.2.1多 Bundle 集成
微前端架構中一般會有個容器應用(container application)將各子應用集成起來,職責如下:
- 渲染公共的頁面元素,比如 header、footer
- 解決橫切關注點(cross-cutting concerns),如身份驗證和導航
- 整合到一個頁面上,并控制微前端的渲染區域和時機
集成方式分為 3 類:
- 服務端集成:如 SSR 拼裝模板
-
關鍵在于如何保證各部分模板(各個微前端)能夠獨立發布,必要的話,甚至可以在服務端也建立一套與前端相對應的結構。

-
每個子服務負責渲染并服務于對應的微前端,主服務向各個子服務發起請求
-
- 構建時集成:如 Code Splitting
- 常見的構建時集成方式是將子應用發布成獨立的 npm 包,共同作為主應用的依賴項,構建生成一個供部署的 JS Bundle
- 然而,構建時集成最大的問題是會在發布階段造成耦合,任何一個子應用有變更,都要整個重新編譯,意味著對于產品局部的小改動也要發布一個新版本,因此,不推薦這種方式
- 運行時集成:如通過 iframe、JS(前端路由)、Web Components 等方式
- iframe 好像不太好(性能、通信成本等),但在這里確實是個合理選項,因為 iframe 無疑是最簡單的方式,還天然支持樣式隔離以及全局變量隔離,但這種原生的隔離性,意味著很難把應用的各個部分聯系到一起,路由控制、歷史棧管理、深度鏈接(deep-linking)、響應式布局等都變得異常復雜,因而限制了 iframe 方案的靈活性
- 前端路由,每個子應用暴露出渲染函數,主應用在啟動時加載各個子應用的獨立 Bundle,之后根據路由規則渲染相應的子應用。目前看來,是最靈活的方式
- Web Components,將每個子應用封裝成自定義 HTML 元素(而不是前端路由方案中的渲染函數),以獲得Shadow DOM帶來的樣式隔離等好處
2.2.2 影響隔離
子應用之間,以及子應用與主應用間的樣式、作用域隔離是必須要考慮的問題,常見解決方案如下:
- 樣式隔離:開發規范(如BEM)、CSS 預處理(如SASS)、模塊定義(如CSS Module)、用 JS 來寫(CSS-in-JS)、以及shadow DOM特性
- 作用域隔離:各種模塊定義(如ES Module、AMD、Common Module、UMD)
2.2.3 資源復用
資源分為以下 3 類:
- 基礎資源:完全不含邏輯功能的圖標、標簽、按鈕等
- UI 組件:含有一定 UI 邏輯的搜索框(如自動完成)、表格(如排序、篩選、分頁)等
- 業務組件:含有業務邏輯
注意:不建議跨子應用復用業務組件,因為會造成高度耦合,增加變更成本
對于公共資源的歸屬和管理:
- 公共資源歸屬于所有人,即沒有明確歸屬
- 公共資源歸集中管理,由專人負責
注意:所有人都能補充公共資源,但要有人(或一個團隊)負責監管,以保證質量、一致性以及正確性
2.2.4 應用間通信
原理
- 使用發布訂閱者模式:一方訂閱,一方發布。
- 使用單例模式:一個工程內使用同一個實例。
- 微前端加載,首先加載父工程,隨后根據配置加載對應的一個或者多個子工程。
- 父工程先一步生成實例,并傳遞給子工程。子工程則使用這個實例初始化自己的實例。 共享同一個實例。
通過自定義事件間接通信是一種避免直接耦合的常用方式,此外,React 的單向數據流模型也能讓依賴關系更加明確,對應到微前端中,從容器應用向子應用傳遞數據與回調函數
無論采用哪種方式,都應該盡可能減少子應用間的通信,以避免大量弱依賴造成的強耦合
2.2.5 測試
- 集成測試:保證子應用間集成的正確性,比如跨子應用的交互操作
- 功能測試:保證頁面組裝的正確性
- 單元測試:保證底層業務邏輯和渲染邏輯的正確性
3、缺點
- 導致依賴項冗余,增加用戶的流量負擔
不同應用之間依賴的包存在很多重復,由于各應用獨立開發、編譯和發布,難免會存在重復依賴的情況。導致不同應用之間需要重復下載依賴,額外再增加了流量和服務端壓力。 - 操作/管理上的復雜性
大幅提升的團隊自治水平可能會讓各個團隊的工作愈加分裂。各團隊只關注自己的業務或者平臺功能,在面向用戶的整體交付方面,會導致對用戶需求和體現不敏感,和響應不及時。
4、應用場景
- 兼容遺留系統
- 原來的系統功能已經完善,并且穩定運行,系統重構任務量大。需要使用新框架,新技術去開發新的應用擴展功能。
- 應用聚合
- 提供很多應用和服務,如何為用戶呈現具有統一用戶體驗的應用聚合成為必須解決的問題
- 團隊間共享
- 不用應用之間往往存在很多可以共享和功能和服務。
- 局部/增量升級
- 一個大的產品由很多應用和服務組成,很多時候只需要對部分應用和服務進行升級。如果是單應用,升級耗時長,風險高,影響可服務性。
5、拆分
- 按照業務拆分
- 按照權限拆分
- 按照變更頻率拆分
- 按照組織結構拆分
- 跟隨后端微服務拆分

浙公網安備 33010602011771號