簡介
Module Federation 是 Webpack 5 的一項改變遊戲規則的功能,允許多個構建在運行時共享代碼。本文從零開始動手配置。

1. 核心概念
| 概念 | 描述 |
|---|---|
| 主持人 | 應用程式載入遠端模組(Shell App) |
| 遠端 | 應用程式為主機公開模組 (MFE) |
| 共享 | 主機與遠端之間共享的依賴關係 |
| remoteEntry.js | 清單檔案包含有關遠端模組的資訊 |
┌─────────────────────────────┐
│ Browser │
│ Shell App (Host) │
│ ┌─────────────────────┐ │
│ │ import('product/ │────────► remoteEntry.js (CDN)
│ │ ProductList') │ │ → chunk-abc.js
│ └─────────────────────┘ │
│ Shared: React 18.2.0 │
│ (loaded ONCE) │
└─────────────────────────────┘
2. 主機設定(Shell App)
// webpack.config.js (Shell App)
const { ModuleFederationPlugin } = require('webpack').container;
module.exports = {
plugins: [
new ModuleFederationPlugin({
name: 'shell',
remotes: {
product: 'product@https://product.cdn.com/remoteEntry.js',
cart: 'cart@https://cart.cdn.com/remoteEntry.js',
},
shared: {
react: { singleton: true, requiredVersion: '^18.2.0' },
'react-dom': { singleton: true, requiredVersion: '^18.2.0' },
},
}),
],
};
3.遠端設定(產品MFE)
// webpack.config.js (Product MFE)
module.exports = {
plugins: [
new ModuleFederationPlugin({
name: 'product',
filename: 'remoteEntry.js',
exposes: {
'./ProductList': './src/components/ProductList',
'./ProductDetail': './src/components/ProductDetail',
},
shared: {
react: { singleton: true, requiredVersion: '^18.2.0' },
'react-dom': { singleton: true, requiredVersion: '^18.2.0' },
},
}),
],
};
4. 在主機中使用
import React, { Suspense } from 'react';
const ProductList = React.lazy(() => import('product/ProductList'));
const MiniCart = React.lazy(() => import('cart/MiniCart'));
function App() {
return (
<div>
<Header />
<MFEErrorBoundary>
<Suspense fallback={<div>Loading products...</div>}>
<ProductList />
</Suspense>
</MFEErrorBoundary>
<Footer />
</div>
);
}
5. 遠端 MFE 的錯誤邊界
class MFEErrorBoundary extends React.Component {
state = { hasError: false };
static getDerivedStateFromError() {
return { hasError: true };
}
render() {
if (this.state.hasError) {
return <div>MFE unavailable. <button onClick={() =>
this.setState({ hasError: false })}>Retry</button></div>;
}
return this.props.children;
}
}
6. 共享依賴管理
shared: {
react: {
singleton: true, // Chỉ load 1 version
requiredVersion: '^18.2.0',
eager: false, // Lazy load (recommended)
strictVersion: false, // Cho phép minor version khác
},
}
版本衝突解決:
Host: [email protected]
Remote A: [email protected] → Dùng shared (Host's version)
Remote B: [email protected] → singleton → dùng 18.2.0 (warning)
Remote C: [email protected] → strictVersion=true → ERROR
7. Vite 模組聯盟
// vite.config.js (Remote)
import federation from '@originjs/vite-plugin-federation';
export default defineConfig({
plugins: [
react(),
federation({
name: 'product',
filename: 'remoteEntry.js',
exposes: {
'./ProductList': './src/components/ProductList',
},
shared: ['react', 'react-dom'],
}),
],
});
總結
- 模組聯合=獨立建置之間的執行時間程式碼共用
- 主機透過以下方式載入遠端模組
remoteEntry.js - 共享依賴項:單例模式避免重複的 React
- 生產所需的誤差邊界
- Vite 透過外掛程式支持,類似語法
下一篇文章: 第 13 課:Shell 應用程式 — 路由、佈局和編排