Webpack 5 Module Federation 是什么?如何使用?
Module Federation
模块联邦允许多个独立构建的应用在运行时共享模块,是微前端的实现方案之一。
核心概念
| 概念 |
说明 |
| Host |
消费远程模块的应用(主应用) |
| Remote |
暴露模块的应用(子应用) |
| Shared |
共享依赖(如 react、vue) |
Remote 配置(子应用)
const { ModuleFederationPlugin } = require('webpack').container
module.exports = {
plugins: [
new ModuleFederationPlugin({
name: 'remoteApp',
filename: 'remoteEntry.js',
exposes: {
'./Button': './src/components/Button',
'./utils': './src/utils'
},
shared: {
react: { singleton: true },
'react-dom': { singleton: true }
}
})
]
}
Host 配置(主应用)
new ModuleFederationPlugin({
name: 'hostApp',
remotes: {
remoteApp: 'remoteApp@http://localhost:3001/remoteEntry.js'
},
shared: {
react: { singleton: true },
'react-dom': { singleton: true }
}
})
使用远程模块
import Button from 'remoteApp/Button'
function App() {
return <Button>Click</Button>
}
const RemoteButton = React.lazy(() => import('remoteApp/Button'))
function App() {
return (
<Suspense fallback="Loading">
<RemoteButton>Click</RemoteButton>
</Suspense>
)
}
shared 详解
shared: {
react: {
singleton: true,
requiredVersion: '^18',
eager: false,
}
}
运行时加载 remote
async function loadRemote(name, module) {
await __webpack_init_sharing__('default')
const container = await loadRemoteContainer(name)
await container.init(__webpack_share_scopes__.default)
const factory = await container.get(module)
return factory()
}
const Button = await loadRemote('remoteApp', './Button')
Module Federation 的优势
- 运行时集成:不需要构建时知道子应用
- 依赖共享:react 等公共依赖只加载一次
- 独立部署:子应用独立构建部署
- 按需加载:远程模块按需 import
vs qiankun
| 特性 |
Module Federation |
qiankun |
| 共享依赖 |
✅ 自动共享 |
❌ 各自加载 |
| 集成粒度 |
组件级 |
应用级 |
| JS 沙箱 |
❌ |
✅ |
| CSS 隔离 |
❌ |
✅ |
| 技术栈 |
需统一(shared) |
可不同 |
Vite 中的 Module Federation
import federation from '@originjs/vite-plugin-federation'
export default {
plugins: [
federation({
name: 'host',
remotes: {
remote: 'http://localhost:3001/assets/remoteEntry.js'
},
shared: ['vue']
})
]
}
适用场景
- 大型应用拆分为多个独立部署的模块
- 共享组件库(设计系统)
- 不同团队协作开发同一应用
注意事项
- 共享依赖的版本要兼容
- 没有原生 JS/CSS 隔离
- 调试时需要注意远程模块的 source map
同分类其他题目