JavaScript模块联邦是Webpack 5引入的模块共享机制,允许不同构建产物之间直接共享模块,无需额外打包依赖,这一特性天然适配微前端架构中应用独立开发、运行时集成的核心需求。通过模块联邦,各个微应用可以独立部署,同时共享公共依赖和通用组件,大幅降低整体应用的包体积,提升加载效率。

模块联邦核心概念
模块联邦中有两个核心角色,理解这两个角色是搭建微前端架构的基础:
- Host(宿主应用):微前端架构中的主应用,负责加载和渲染各个微应用,也可以作为模块提供者共享自身模块。
- Remote(远程应用):微前端架构中的子应用,独立开发部署,通过模块联邦暴露自身模块供宿主或其他应用使用。
微前端架构搭建步骤
1. 初始化项目结构
我们创建两个独立项目,分别是主应用host-app和子应用remote-app,两个项目都基于Webpack 5构建。
2. 配置子应用(Remote)
子应用需要暴露自身的入口模块,让其他应用可以远程加载。首先在remote-app的webpack配置中添加模块联邦插件:
const ModuleFederationPlugin = require('webpack').container.ModuleFederationPlugin;
module.exports = {
mode: 'development',
devServer: {
port: 3001, // 子应用运行端口
headers: {
'Access-Control-Allow-Origin': '*' // 允许跨域加载模块
}
},
plugins: [
new ModuleFederationPlugin({
name: 'remote_app', // 远程应用唯一标识
filename: 'remoteEntry.js', // 暴露的模块清单文件名
exposes: {
// 暴露子应用的App组件,路径为./App
'./App': './src/App.js'
},
shared: {
// 共享react和react-dom,避免重复加载
react: { singleton: true },
'react-dom': { singleton: true }
}
})
]
};
子应用的App.js内容如下:
import React from 'react';
const App = () => {
return (
<div style={{ padding: '20px', border: '1px solid #ccc' }}>
<h3>我是远程子应用</h3>
<p>这个组件通过模块联邦暴露给主应用使用</p>
</div>
);
};
export default App;
3. 配置主应用(Host)
主应用需要声明要加载的远程应用,在host-app的webpack配置中添加对应配置:
const ModuleFederationPlugin = require('webpack').container.ModuleFederationPlugin;
module.exports = {
mode: 'development',
devServer: {
port: 3000, // 主应用运行端口
},
plugins: [
new ModuleFederationPlugin({
name: 'host_app', // 主应用唯一标识
remotes: {
// 声明远程应用,remote_app是子应用配置的name,地址是子应用的remoteEntry.js路径
remote_app: 'remote_app@http://localhost:3001/remoteEntry.js'
},
shared: {
// 和子应用共享相同的依赖
react: { singleton: true },
'react-dom': { singleton: true }
}
})
]
};
4. 主应用加载远程模块
主应用通过动态导入的方式加载远程子应用的组件,代码如下:
import React, { Suspense } from 'react';
import ReactDOM from 'react-dom/client';
// 动态导入远程子应用的App组件
const RemoteApp = React.lazy(() => import('remote_app/App'));
const App = () => {
return (
<div>
<h1>微前端主应用</h1>
<Suspense fallback={<div>加载子应用中...</div>}>
<RemoteApp />
</Suspense>
</div>
);
};
const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(<App />);
关键配置说明
| 配置项 | 作用 |
|---|---|
| singleton: true | 确保共享的依赖只加载一个实例,避免多版本冲突 |
| exposes | 声明当前应用要暴露给外部的模块路径和别名 |
| remotes | 声明当前应用要加载的远程应用地址和别名 |
| filename | 指定生成的模块清单文件名,默认是remoteEntry.js |
常见问题与解决方案
跨域问题
远程应用的资源需要允许跨域访问,否则主应用无法加载远程模块,需要在子应用的devServer配置中添加Access-Control-Allow-Origin响应头,生产环境可以通过Nginx配置跨域规则。
依赖版本不一致
如果主应用和子应用的共享依赖版本差异较大,可能导致运行报错,建议统一共享依赖的版本,或者通过requiredVersion配置指定依赖的最低版本要求。
加载失败处理
可以在动态导入远程模块时添加错误捕获逻辑,当远程应用不可用时展示兜底内容,提升用户体验:
const loadRemoteApp = () => {
return import('remote_app/App').catch(() => {
// 加载失败返回兜底组件
return {
default: () => <div>子应用加载失败,请稍后重试</div>
};
});
};
const RemoteApp = React.lazy(loadRemoteApp);
基于JavaScript模块联邦的微前端架构无需引入额外的微前端框架,配置简单,运行时集成的方式也让各个微应用的迭代互不影响,非常适合中大型前端应用的拆分和重构。实际落地时可以根据业务需求扩展模块共享范围,优化加载策略,进一步提升架构的可用性。
JavaScript模块联邦微前端架构Webpack修改时间:2026-06-13 22:18:35