The Own Lab The Own Lab

微前端架構概覽

什麼是 Micro-Frontend、為什麼需要它,以及主流架構模式的比較

Overview##

想像一個電商網站:首頁、商品頁、購物車、結帳、會員中心。在傳統的 monolithic frontend 架構下,這些全部打包在同一個 SPA 裡,由同一個團隊、同一個 repo、同一個 CI/CD pipeline 管理。

當團隊從 5 人長到 30 人,問題就來了:

  • 一個人改了購物車的程式碼,整個網站都要重新 build 和部署
  • 三個團隊要同時 merge 到同一個 main branch,衝突不斷
  • 想把商品頁從 React 15 升級到 React 19,但購物車還沒準備好,只能一起等

Micro-Frontend 就是把後端微服務的概念搬到前端:每個功能區塊是獨立的應用,可以由不同團隊獨立開發、測試、部署。

Architecture##

核心原則###

graph TD
  subgraph Monolith
    A[Single SPA] --> B[Homepage]
    A --> C[Product Page]
    A --> D[Cart]
    A --> E[Checkout]
  end

  subgraph Micro-Frontend
    F[Shell / Host] --> G[Team A: Homepage]
    F --> H[Team B: Product Page]
    F --> I[Team C: Cart + Checkout]
  end

Micro-Frontend 的核心原則:

原則說明
獨立部署每個 micro-frontend 可以單獨 build 和 deploy,不影響其他部分
團隊自治每個團隊擁有自己的 repo、CI/CD、技術選型
技術無關Team A 用 React、Team B 用 Vue,甚至 Team C 用 Svelte 都行
隔離性一個 micro-frontend 的 bug 不該讓整個網站崩潰

Note

Micro-Frontend 不是銀彈。它解決的是組織規模化的問題,不是技術問題。如果你的團隊只有 3-5 人,monolith 幾乎一定是更好的選擇。架構的複雜度應該匹配組織的複雜度。

主流整合模式###

實現 Micro-Frontend 有多種方式,每種都有不同的取捨:

1. iframe####

最古老也最簡單的方式 — 每個 micro-frontend 放在一個 <iframe> 裡。

<!-- Shell application -->
<nav><!-- global navigation --></nav>
<main>
  <iframe src="https://team-a.example.com/product-page" />
</main>

優點: 完全隔離,技術完全無關,每個 iframe 是獨立的瀏覽器 context。

缺點: 效能差(每個 iframe 載入完整的 HTML/CSS/JS)、無法共享 state、SEO 困難、使用者體驗差(無法跨 iframe 做動畫或共享樣式)。

2. Web Components####

每個 micro-frontend 包裝成 Custom Element,透過 Shadow DOM 實現樣式隔離。

// Team B: Product Card as Web Component
class ProductCard extends HTMLElement {
  connectedCallback() {
    const shadow = this.attachShadow({ mode: 'open' });
    const productId = this.getAttribute('product-id');

    shadow.innerHTML = `
      <style>
        .card { border: 1px solid #e5e7eb; padding: 16px; }
      </style>
      <div class="card">
        <h3>Product ${productId}</h3>
        <slot name="actions"></slot>
      </div>
    `;
  }
}

customElements.define('product-card', ProductCard);
<!-- Shell: use the Web Component -->
<product-card product-id="42">
  <button slot="actions">Add to Cart</button>
</product-card>

優點: 瀏覽器原生支援、樣式天然隔離、框架無關。

缺點: SSR 支援有限、跨 micro-frontend 共享狀態需要額外方案(Custom Events 或 shared store)、Shadow DOM 的樣式隔離有時反而讓全域主題很難套用。

3. Module Federation####

Webpack 5 / Rspack 內建的功能。每個 micro-frontend 是一個獨立的 webpack build,在 runtime 動態載入彼此的模組。

// Team A: expose a component
// webpack.config.ts
new ModuleFederationPlugin({
  name: 'productApp',
  filename: 'remoteEntry.js',
  exposes: {
    './ProductCard': './src/components/ProductCard',
  },
  shared: {
    react: { singleton: true, requiredVersion: '^18.0.0' },
    'react-dom': { singleton: true, requiredVersion: '^18.0.0' },
  },
});
// Shell: consume the remote component
const ProductCard = React.lazy(
  () => import('productApp/ProductCard')
);

function App() {
  return (
    <React.Suspense fallback={<div>Loading...</div>}>
      <ProductCard productId="42" />
    </React.Suspense>
  );
}

優點: 可以共享依賴(React 只載入一份)、開發體驗接近 monolith(直接 import)、支援 TypeScript 型別。

缺點: 綁定 webpack / Rspack 生態系、設定有學習門檻、shared dependency 版本衝突需要仔細管理。

模式比較###

維度iframeWeb ComponentsModule Federation
隔離性最強(獨立 context)強(Shadow DOM)中(shared scope)
效能差(重複載入)最好(共享依賴)
共享狀態困難Custom Events直接 import
技術無關完全完全限 webpack 生態
開發體驗好(接近 monolith)
SSR困難有限支援
學習曲線

Tip

如何選擇? 如果團隊技術棧差異極大(React + Angular + jQuery legacy),用 iframe 或 Web Components。如果團隊都在 webpack 生態系內,Module Federation 是最佳選擇 — 效能最好、開發體驗最接近 monolith。

通訊模式###

不管用哪種整合方式,micro-frontend 之間總需要溝通。常見的做法:

graph LR
  A[Product Page] -->|CustomEvent| B[Event Bus]
  B -->|CustomEvent| C[Cart]
  D[Shell] -->|Props / Attributes| A
  D -->|Props / Attributes| C
  E[Shared Store] <-->|subscribe| A
  E <-->|subscribe| C
方式適用場景範例
Props / Attributes父 → 子的單向資料流Shell 傳 userId 給子應用
Custom Events鬆耦合的跨應用通知Product Page 發出 add-to-cart event
Shared Store需要同步的全域狀態登入狀態、購物車數量
URL / Router頁面級的導航Shell 統一管理路由

Warning

避免讓 micro-frontend 之間產生太多通訊。如果兩個 micro-frontend 需要頻繁交換資料,通常代表它們不該被拆開。Micro-Frontend 的邊界應該對齊業務邊界,而不是技術邊界。

Summary##

  • Micro-Frontend 是前端的微服務架構。 每個功能區塊獨立開發、測試、部署,解決大型團隊的協作瓶頸。
  • 三種主流整合模式: iframe(最隔離)、Web Components(瀏覽器原生)、Module Federation(最佳效能與開發體驗)。
  • 選擇標準看團隊,不看技術。 如果團隊都在 webpack 生態系,Module Federation 是首選。
  • 通訊越少越好。 如果兩個 micro-frontend 需要頻繁溝通,代表邊界切錯了。
  • 不要為了架構而架構。 小團隊用 monolith,大團隊才需要 Micro-Frontend。

留言 (0)

登入後即可留言