各位在前端戰場打滾的開發者,如果你手上的後台系統已經膨脹到幾十個模組、編譯一次要等兩分鐘、任何一個小需求都要全量發版,那麼這篇文章就是為你寫的。在 CSF 這類情報大屏專案裡,資產管理、告警、日誌、總覽各自是一個龐大子系統,把它們塞進同一個 Vue 單體應用,遲早會遇到「牽一髮而動全身」的維護噩夢。微前端(Micro-Frontend)正是為了解決這個問題而生——它讓不同團隊可以獨立開發、獨立部署、獨立運行,最後像拼樂高一樣組裝成一個完整產品。
一、什麼是微前端
微前端的核心思想,是把「後端微服務」的拆分理念搬到前端:把一個巨型單頁應用(SPA)拆成多個可以獨立運作的小應用,再由一個「容器」把它們掛載到同一個頁面上。對使用者來說,看到的是一個統一的網站;對開發團隊來說,每個子應用可以用不同的技術棧、不同的發版節奏。
- 獨立開發:各子應用由不同小組維護,互不干擾。
- 獨立部署:改一個模組不必重新打包整個系統。
- 技術異構:新子應用可以用新版框架,舊的暫時不用重寫。
二、為什麼大型後台特別需要它
以 CSF 這種情報平台為例,告警管理和日誌檢索是兩個差異很大的領域,迭代頻率也不同。如果全部綁在同一個倉庫,任何一次「npm install」或「build」都要把所有模組一起編譯,開發體驗和發版風險都會直線上升。微前端把單體應用的「編譯粒度」降到子應用級別,哪裡改動就編譯哪裡,顯著縮短反饋循環。
三、用 Module Federation 實戰拆分
Webpack 5 與 Vite 都內建了 Module Federation(模組聯邦),它是當前最主流的實現方案。下面以 Vite + @module-federation/vite 套件為例,示範如何把「日誌檢索」拆成一個可被主應用遠端載入的子應用。
步驟 1:在子應用中暴露模組
先在子應用(日誌檢索)的 vite.config.ts 中宣告要對外暴露的入口:
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
import federation from '@module-federation/vite'
export default defineConfig({
plugins: [
vue(),
federation({
name: 'logRetrieval',
filename: 'remoteEntry.js',
exposes: {
'./LogRetrievalApp': './src/App.vue',
},
shared: ['vue', 'pinia'],
}),
],
})
步驟 2:在主應用中遠端引入
回到主容器應用,宣告要從遠端拉取哪個子應用:
import federation from '@module-federation/vite'
export default defineConfig({
plugins: [
vue(),
federation({
name: 'shell',
remotes: {
logRetrieval: 'http://localhost:5172/assets/remoteEntry.js',
},
shared: ['vue', 'pinia'],
}),
],
})
步驟 3:動態掛載子應用
主應用在路由對應頁面時,動態 import 遠端模組並掛載:
const mountLogRetrieval = async () => {
const remote = await import('logRetrieval/LogRetrievalApp')
// 掛載到指定的 DOM 容器
remote.default.mount('#log-container')
}
四、落地時的幾個重點
重點:共享依賴必須對齊版本。上面 shared: ['vue','pinia'] 就是為了避免主應用與子應用各帶一份 Vue,導致兩套響應式系統互相不認識。若版本不一致,頁面會出現「元件無法渲染」或「狀態讀不到」的玄學 bug。
重點:路由與樣式隔離要提前規劃。多個子應用同時存在時,全域 CSS 與路由前綴容易打架,建議每個子應用使用帶命名空間的樣式與獨立路由前綴(例如 /log/)。
結語
微前端不是銀彈,它會帶來跨應用溝通、版本治理的新成本。特別注意:當你的系統規模還沒到「多團隊協作、編譯已明顯拖慢迭代」的程度,先別急著上微前端,模組化拆分可能就夠用了。把它留給真正龐大的戰場。
互動話題:你們團隊有遇過「單體前端編譯太慢、發版太重」的痛點嗎?是選了微前端,還是用 Monorepo + 模組化就解決了?歡迎留言分享你的取捨。