從微前端開始:用 Module Federation 拆分大型前端應用的實戰指南

各位在前端戰場打滾的開發者,如果你手上的後台系統已經膨脹到幾十個模組、編譯一次要等兩分鐘、任何一個小需求都要全量發版,那麼這篇文章就是為你寫的。在 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 + 模組化就解決了?歡迎留言分享你的取捨。