Webpack 模块联邦(Module Federation)
模块联邦(Module Federation) 是 Webpack 5 推出的一个革命性功能,它让 多个独立构建的项目可以共享代码或组件,甚至在运行时动态加载对方的模块。
传统问题:
在大型前端体系中,尤其是 微前端架构 场景:
-
各子应用需要复用组件(比如导航栏、登录模块等)
-
每个子应用独立部署、独立构建
-
想要共享组件,但不能打包到每个项目里(否则体积大、更新麻烦)
模块联邦的解决方案:
-
允许一个应用暴露出模块(exposes)
-
另一个应用在运行时去加载这个模块(remotes)
-
两边可以共享依赖(如 react、vue、lodash 等)
-
实现真正的跨应用模块复用
模块联邦依靠 Webpack 内置的运行时机制:
-
暴露端(Host / Remote)
- 使用 ModuleFederationPlugin 配置 exposes 把模块暴露出去;
-
消费端(Consumer)
- 使用 remotes 指定远程模块来源;
-
运行时动态加载
- 当消费端访问远程模块时,Webpack 会在运行时拉取远程 bundle 并注册模块;
-
共享依赖
- 通过 shared 声明两端共用依赖,避免重复加载。
配置示例
主应用(Host)
// webpack.config.js
new ModuleFederationPlugin({name: 'hostApp',remotes: {// 告诉主应用,从 http://localhost:3001/remoteEntry.js 加载 remoteApp 的模块remoteApp: 'remoteApp@http://localhost:3001/remoteEntry.js'},shared: {react: { singleton: true, requiredVersion: '^18.0.0' },'react-dom': { singleton: true }}
});
远程应用(Remote)
new ModuleFederationPlugin({name: 'remoteApp',filename: 'remoteEntry.js', // 暴露清单文件exposes: {'./Button': './src/components/Button' // 暴露组件},shared: {react: { singleton: true },'react-dom': { singleton: true }}
});
主应用中使用远程组件:
import React from 'react';// 动态加载远程模块
const RemoteButton = React.lazy(() => import('remoteApp/Button'));export default function App() {return (<React.Suspense fallback="Loading..."><RemoteButton /></React.Suspense>);
}
配置项:
名称 | 含义 |
---|---|
name | 应用名称,暴露或引用时的标识 |
filename | 构建输出的入口文件,用于远程加载 |
exposes | 当前应用暴露出的模块 |
remotes | 当前应用依赖的远程模块 |
shared | 公共依赖,防止重复加载版本冲突 |
使用场景:
-
微前端架构
- 多个独立子应用共享 UI 组件、工具库、公共逻辑。
-
团队协作开发
- 团队 A、B 各自维护独立项目,但需要共享部分模块。
-
动态加载独立功能模块
- 像插件系统,按需从服务器加载新模块。
常见问题:
-
版本冲突
- 使用 shared 的 singleton 和 requiredVersion 控制依赖版本。
-
远程模块加载失败
-
检查 remoteEntry.js 是否能被访问;
-
跨域时配置 CORS。
-
-
类型支持(TS项目)
- 可以通过 declare module ‘remoteApp/Button’ 声明类型。
对比微前端
对比项 | 模块联邦 | 微前端框架(如 qiankun) |
---|---|---|
目的 | 代码级模块共享 | 应用级独立运行 |
加载方式 | Webpack 运行时加载 | iframe / sandbox / 子路由等 |
适用场景 | 组件共享、跨项目复用 | 独立项目集成 |
构建关系 | 构建时/运行时共享 | 完全独立构建 |
实际项目中常常 模块联邦 + 微前端 一起使用。