前端 Module Federation 架構介紹
前言
隨著前端應用越來越龐大,單一 repo 難以維護、多個團隊同時開發同一個專案也容易互相干擾。微前端(Micro Frontend)的概念因此逐漸受到關注,而 Module Federation 是其中一種實作方式,最早由 Webpack 5 在 2020 年正式引入。
簡單來說,Module Federation 讓不同的應用程式可以在執行期間(runtime)動態地載入彼此的模組,不需要事先把所有程式碼打包在一起。
什麼是 Module Federation
傳統的前端打包方式,是把所有的程式碼在建置時(build time)合併成一個或幾個 bundle 檔案,部署後整包上線。這在小型專案沒什麼問題,但當專案規模變大、團隊人數增加,問題就開始出現:每次有任何一個小改動,整個應用都要重新建置和部署。
Module Federation 的做法不同。它讓每個獨立應用(稱為 remote)可以對外暴露(expose)自己的模組,而另一個應用(稱為 host)則可以在執行時動態去抓這些模組來用,就像引入自己本地的程式碼一樣。
這種方式讓多個團隊可以各自維護、各自部署,彼此之間只透過定義好的介面來溝通。
基本運作方式
以 Webpack 5 為例,設定上大概長這樣:
Remote(提供模組的應用)
// webpack.config.js
const { ModuleFederationPlugin } = require('webpack').container
module.exports = {
plugins: [
new ModuleFederationPlugin({
name: 'remoteApp',
filename: 'remoteEntry.js',
exposes: {
'./Button': './src/components/Button',
},
shared: ['react', 'react-dom'],
}),
],
}
Host(使用模組的應用)
// webpack.config.js
const { ModuleFederationPlugin } = require('webpack').container
module.exports = {
plugins: [
new ModuleFederationPlugin({
name: 'hostApp',
remotes: {
remoteApp: 'remoteApp@http://localhost:3001/remoteEntry.js',
},
shared: ['react', 'react-dom'],
}),
],
}
Host 在程式碼裡就可以直接這樣用:
import Button from 'remoteApp/Button'
Webpack 會在執行時去 http://localhost:3001/remoteEntry.js 抓取 Button 元件,不是在建置時打包進去的。
優點
獨立部署
每個子應用可以各自建置、各自部署,改 A 不影響 B。這對多團隊協作的大型專案來說很重要,可以縮短部署週期,減少相互等待的成本。
共用依賴,避免重複載入
透過 shared 設定,多個應用可以共用同一份 React 或其他套件,不會每個應用各載一份,減少使用者瀏覽器的載入量。
彈性的架構組合
子應用可以是用不同技術棧(例如一個用 React、一個用 Vue)實作的,只要 host 正確加載即可。這讓舊系統的漸進式遷移成為可能,不需要一次全部重寫。
模組層級的共用
Module Federation 不只能共用整個頁面,也可以共用單一元件、工具函數、甚至設計系統,比起傳統的 npm 套件方式,更新更即時,不需要發版。
缺點
版本管理複雜
各個子應用各自維護,依賴版本很容易出現不一致的問題。例如 host 用 React 18,remote 用 React 17,若 shared 設定沒做好,可能會導致問題難以排查。
執行時錯誤難以預測
相較於傳統打包在建置時就能發現問題,Module Federation 的模組是在執行時動態載入的,若 remote 掛掉或模組介面改了,host 不會在建置時得到任何警告,只會在使用者瀏覽時才出錯。
本地開發體驗較差
要在本地測試整個系統,需要同時把多個應用跑起來,並確保 URL 和設定都正確。這比單一 monorepo 的開發體驗要麻煩許多,特別是在有很多子應用的情況下。
效能難以精準掌控
動態載入模組帶來彈性的同時,也增加了網路請求的不確定性。如果 remote 的 remoteEntry.js 回應慢,整個載入流程就會卡住,需要額外處理 loading 狀態和錯誤邊界(Error Boundary)。
測試難度提升
由於子應用之間的整合是在執行時才發生,整合測試的覆蓋難度比傳統架構高。通常需要另外搭建一套 E2E 測試環境來驗證各個應用組合後的行為。
小結
Module Federation 解決了大型前端專案在多團隊協作、獨立部署上的痛點,讓各個子應用可以真正做到邏輯分離、獨立維護。
不過它不是萬靈丹。引入它之後,版本管理、錯誤處理、本地開發體驗都需要額外的投入。如果團隊規模不大,或專案複雜度還不到需要拆分的程度,直接用 monorepo 加上清楚的模組邊界可能是更務實的選擇。
適不適合用 Module Federation,取決於你的團隊規模和專案需求,而不是技術本身是否夠新或夠潮。