Webpack的Module Federation(模块联邦)是Webpack 5推出的核心特性,它允许不同构建产物在运行时相互加载对方暴露的模块,无需提前打包到同一个项目中,非常适合用来搭建微前端架构。这种方案可以让各个子应用独立开发、独立部署,同时共享公共依赖和通用组件,大幅降低整体应用的打包体积和维护成本。

Module Federation核心概念
在使用该特性前,需要先理解几个核心配置项的作用:
- name:当前应用的唯一标识,其他应用通过这个名称来引用该应用暴露的模块
- filename:当前应用暴露的远程入口文件名,其他应用会通过这个文件获取模块信息
- exposes:声明当前应用要暴露给外部使用的模块路径和对应的暴露名称
- remotes:声明当前应用需要加载的其他远程应用的名称和对应的入口文件地址
- shared:声明需要共享的依赖,避免多个应用重复打包同一个依赖
子应用配置示例
首先我们搭建一个子应用,这里以React子应用为例,先配置Webpack的Module Federation相关参数:
// 子应用 webpack.config.js
const { ModuleFederationPlugin } = require('webpack').container;
const deps = require('./package.json').dependencies;
module.exports = {
mode: 'development',
devServer: {
port: 3001, // 子应用运行端口
historyApiFallback: true
},
plugins: [
new ModuleFederationPlugin({
name: 'app1', // 子应用唯一名称
filename: 'remoteEntry.js', // 远程入口文件名
exposes: {
// 暴露子应用的App组件,外部可以通过 app1/App 访问
'./App': './src/App'
},
shared: {
// 共享react和react-dom依赖,单例模式避免重复加载
react: {
singleton: true,
requiredVersion: deps.react
},
'react-dom': {
singleton: true,
requiredVersion: deps['react-dom']
}
}
})
]
};子应用的入口文件不需要做特殊修改,正常导出根组件即可:
// 子应用 src/index.js
import React from 'react';
import ReactDOM from 'react-dom';
import App from './App';
// 需要同时支持独立运行和被远程加载两种场景
if (!window.__POWERED_BY_REMOTE__) {
ReactDOM.render(<App />, document.getElementById('root'));
}
// 暴露给外部加载的方法
export const mount = (container) => {
ReactDOM.render(<App />, container);
};
export const unmount = (container) => {
ReactDOM.unmountComponentAtNode(container);
};主应用配置示例
主应用需要配置远程应用的引用信息,同样以React主应用为例:
// 主应用 webpack.config.js
const { ModuleFederationPlugin } = require('webpack').container;
const deps = require('./package.json').dependencies;
module.exports = {
mode: 'development',
devServer: {
port: 3000, // 主应用运行端口
historyApiFallback: true
},
plugins: [
new ModuleFederationPlugin({
name: 'host', // 主应用唯一名称
remotes: {
// 配置远程子应用,app1对应子应用的name,地址是子应用remoteEntry.js的访问地址
app1: 'app1@http://localhost:3001/remoteEntry.js'
},
shared: {
// 共享和子应用相同的依赖,保证版本一致
react: {
singleton: true,
requiredVersion: deps.react
},
'react-dom': {
singleton: true,
requiredVersion: deps['react-dom']
}
}
})
]
};主应用中需要动态加载远程模块,这里使用React的懒加载结合<Suspense>实现:
// 主应用 src/App.js
import React, { Suspense } from 'react';
// 懒加载远程子应用的App组件
const RemoteApp = React.lazy(() => import('app1/App'));
function App() {
return (
<div>
<h1>主应用</h1>
<div style={{ border: '1px solid #ccc', padding: '20px' }}>
<h2>远程子应用区域</h2>
<Suspense fallback={<div>加载子应用中...</div>}>
<RemoteApp />
</Suspense>
</div>
</div>
);
}
export default App;进阶使用场景
跨应用通信
Module Federation本身不提供通信能力,可通过以下几种方式实现跨应用数据传递:
- 主应用通过props向远程组件传递数据和回调函数
- 使用全局状态管理工具,比如将Redux、MobX的store挂载到window对象上共享
- 使用自定义事件系统,通过dispatchEvent和addEventListener实现事件通信
依赖版本冲突处理
当多个应用的共享依赖版本不一致时,可以在shared配置中添加版本校验规则:
shared: {
react: {
singleton: true,
requiredVersion: deps.react,
// 版本不匹配时仍然加载,避免应用崩溃
strictVersion: false
}
}生产环境部署
生产环境需要保证远程入口文件的地址可访问,通常通过Nginx配置静态资源路径,将子应用的打包产物部署到对应的服务器路径下,主应用配置对应的远程地址即可。如果子应用地址使用ipipp.com域名,记得替换对应的访问地址即可。
注意事项
- 所有应用的共享依赖版本尽量保持一致,避免出现运行时的兼容性问题
- 远程模块的加载是异步的,需要处理加载失败、超时等异常情况
- 子应用的路由如果使用BrowserRouter,需要和主应用的路由规则做好适配,避免路由冲突
- 开发环境需要保证子应用先于主应用启动,或者主应用做好远程模块加载的重试逻辑
WebpackModule_Federation微前端模块共享修改时间:2026-06-03 01:52:30