這裏是突然勤奮的 Zhuo,持續更新文檔中。
本文只涉及到 module-federation 微前端方案的設計層面分享,關於具體實現,可以參考寫的簡單例子;所有的設計圖自取,如果對你有一些啓發,請點個 star
背景
團隊從瀑布流模式轉變為敏捷模式,將整個項目團隊劃分為多個小組並行開發,多小組同時升級的分支處理和代碼衝突之類的問題頻繁出現。於是接到了組內一個技術需求:《模塊支持單獨升級和部署》。目前,我們開發和維護代碼的現狀:
- 一個倉庫包含了所有的業務組的前端代碼
- 只能一起打包出一個整包,也無法單獨部署
- 後端已完成微服務的拆分
如上所述,雖然一般場景通過 git 多分支管理能解決【獨立開發】和【發佈】的問題,但是一遇到【多團隊同時發佈】的場景就讓人頭疼了:
- 需要拉上各個團隊的負責人,反覆確認當天能否正常上線
- 上線分支排列組合(release-a、release-b、release-ab )預防某一個團隊突發問題不上線
- 測試工作量增加:原本只要驗收一個代碼包,現在還要驗證多個代碼包功能(> 1)
看一眼分支模型:
既然提出了已有問題,為了解決這些問題,我們意識到和後端一樣將整個項目拆分成若干的子應用,將它們也變成微服務,不就可以解決目前的困境了嗎?自然而然我們就想到了“微前端”的概念。有目標,就好發力了,我們參考了業務優秀方案,同時結合了自身實際情況,最終決定用webpack5 module federation 特性來進行微前端的實踐與落地。
需求分析
外部需求
- 拆分解耦
- 單獨打包,獨立部署
- 不影響現在的用户體驗
內部需求
- 不影響開發體驗
- 方案對原業務代碼侵入性最低
- 學習成本低
- 統一技術棧
- 前端灰度發佈
方案選擇
方案:
-
應用微服務化,諸如 qiankun2
- 存在性能問題,且沙箱逃逸問題難解決,放棄
-
微件化:通過組合多個獨立應用、組件來構建一個單體應用,例如 Module Federation
- 在接入第三方應用上存在的問題比較大,但是對於我們想要達到【獨立升級】的效果來説,此短板可以接受
-
結合 Web Components 構建,例如 micro-app
- 在處理沙箱的性能問題和逃逸問題上雖然比方案1更優秀,但這兩個問題出現還是難解決,且目前官方維護的頻率及未有穩定版本,放棄
-
MPA+路由分發
- 相當將原本的一個系統拆成多個系統,體驗上無法接受,放棄
-
MPA + iframe
- iframe 在性能和用户體驗上的問題也是無法接受,放棄
-
純 Web Component 進行構建應用
- 需要用一個新的基礎方案將整個項目的代碼重構,工作量上無法接受,放棄
最終採用方案2:module federation。
微前端實踐
通過方案的分析以及項目實際情況的梳理,我們確定了微前端的整體方案,輸出組件圖,如下圖所示:
可以看到,整個方案非常簡單:按照開發小組進行路由級別的拆分,整個系統可分為兩個部分:
- 基座應用:用於管理子應用的路由切換、註冊子應用的路由和全局 Store 層、提供全局庫和複用層
- 子應用:用於開發子應用業務代碼,一個子應用對應一個開發小組,並且管理自己的路由、語言包、埋點、Store
基座應用和子應用聯繫起來的橋樑則是入口文件:remoteEntry.js。這可以讓基座應用準確地發現子應用資源的路徑從而進行加載。
因為依賴了remoteEntry.js進行關聯,所以這個文件不會加 hash 後綴,這就要求對該命名的文件全部設置協商緩存,不再是強緩存。
微前端下的架構變化
在整個方案的改造之後,我們的項目整體的架構變成了如下圖展示的樣子:
前端側的代碼按照小組特性拆分成若干個子應用:
- 每個子應用只擁有自己相關的代碼,基座應用可以看成比較特殊的子應用,它提供工程能力,最好不要有業務代碼
- 將應用代碼劃分到
packages/apps文件下, 通過monorepo + pnpm進行管理依賴 - 所有的文件夾進行單獨的打包構建,搭配
Docker + Kubernetes構建成單獨的容器(紅色部分內所有的子應用都是單獨的容器)變成真正的微服務 - 通過
ingressroute + nginx加載不同容器之間的子應用資源
以上的變化,讓拆分出來的子應用能夠獨立開發 - 維護 - 發佈之外,還使得我們前端應用升級時的 灰度 - 部署 - 回滾 操作變得更加簡單、快速。
部署方案
在達成獨立部署上線的目標之後,所有的子應用都是獨立的,發佈不需要依賴於任何應用。只需要確認開發修改了哪些子應用的代碼,那麼就升級對應的子應用即可。
具體流程:
- 開發修改了 A 應用的代碼,上庫
- 打包平台(千流,公司自建)識別到具體變更的代碼路徑,對 A 應用進行打包,生成鏡像容器、版本號等,推送到鏡像平台
- 升級對應服務
雖然步驟是這些,但是在開發人員這裏,他只需要提供本次升級的版本號(1.0.xxx)即可,背後流程不需要深入瞭解。
回滾方案
得益於 Docker + Kubernets ,前端的回滾只需要執行一條 helm 命令即可。除此沒有其他的內容。
總結
總的來説,我們完成了以下的目標:
- [x] 代碼拆分解耦
- [x] 單獨打包,獨立部署
- [x] 不影響現在的用户體驗:沒有引入其他類庫,也沒有使用 iframe
- [x] 不影響開發體驗:支持熱更新
- [x] 方案對原業務代碼侵入性最低:核心工作量在代碼拆分,webpack的配置並沒有多少工作量
- [x] 學習成本低:基本沒有學習成本
- [x] 統一技術棧:本來就是一個項目
- [x] 前端灰度發佈
學習鏈接
感謝以下文章的作者/團隊分享的文章,提供了很好的思路。
- Module federation 原理研究
- Revolutionizing Micro Frontends with Webpack 5, Module Federation and Bit
- How to Build a Micro Frontend with Webpack's Module Federation Plugin
- Webpack Module Federation
- Module Federation Examples
- https://medium.com/@A__G__B/i...
- EMP-面向未來微前端方案正式開源了!
- micro-app 介紹
- 可能是你見過最完善的微前端解決方案
- 字節跳動是如何落地微前端的
- 微前端在美團外賣的實踐
都看到這裏了,幫忙點個讚唄~