模块联邦(Module Federation)是 Webpack 5 引入的一项革命性功能,它允许在独立的 JavaScript 应用程序之间动态共享代码模块,从而实现微前端架构和跨应用代码复用。核心思想是"一个应用可以消费另一个应用暴露的模块"。
远程应用 Webpack 配置暴露出口
const { ModuleFederationPlugin } = require('webpack').container;
const HtmlWebpackPlugin = require('html-webpack-plugin');
module.exports = {
mode: 'development',
entry: './src/index.js', // 主入口,我们简化一下,可以直接是bootstrap.js
devServer: {
port: 3001, // 远程应用运行在3001端口
hot: true,
},
module: {
rules: [
{
test: /\.jsx?$/,
exclude: /node_modules/,
use: {
loader: 'babel-loader',
options: {
presets: ['@babel/preset-react'],
},
},
},
],
},
plugins: [
// 模块联邦插件
new ModuleFederationPlugin({
name: 'app_components', // 唯一名称,供其他应用引用
filename: 'remoteEntry.js', // 入口清单文件名,固定
exposes: { // 暴露的模块列表
'./Button': './src/components/Button', // 别名: 模块路径
'./Header': './src/components/Header',
},
shared: { // 共享的库
react: { singleton: true, requiredVersion: '^18.0.0' },
'react-dom': { singleton: true, requiredVersion: '^18.0.0' },
},
}),
new HtmlWebpackPlugin({
template: './public/index.html',
}),
],
};
主机应用使用
import React from 'react';
import ReactDOM from 'react-dom/client';
import LocalComponent from './LocalComponent'; // 本地的一个组件
// 1. 动态导入远程模块
const RemoteButton = React.lazy(() => import('app_components/Button'));
const RemoteHeader = React.lazy(() => import('app_components/Header'));
const App = () => {
return (
<div style={{ padding: '20px', border: '2px solid #ccc', margin: '20px' }}>
<h2>主应用 (运行在 localhost:3000)</h2>
<LocalComponent />
<hr />
{/* 2. 使用Suspense加载远程组件 */}
<React.Suspense fallback={<div>正在加载远程组件...</div>}>
<RemoteHeader title="我是远程的标题" />
<RemoteButton onClick={() => alert('按钮来自远程应用!')}>
点我
</RemoteButton>
</React.Suspense>
</div>
);
};
const root = ReactDOM.createDocument.getElementById('root');
root.render(<App />);
Webpack 配置引入入口
const { ModuleFederationPlugin } = require('webpack').container;
const HtmlWebpackPlugin = require('html-webpack-plugin');
module.exports = {
mode: 'development',
entry: './src/index.js',
devServer: {
port: 3000, // 主机应用运行在3000端口
hot: true,
},
module: { /* ... 类似远程的babel规则 ... */ },
plugins: [
new ModuleFederationPlugin({
name: 'main_app',
remotes: { // 定义远程应用
// 格式: “远程应用在联邦中的名称”@“远程应用的入口文件地址”
app_components: 'app_components@http://localhost:3001/remoteEntry.js',
},
shared: { // 共享的库,必须和远程应用协调一致
react: { singleton: true, requiredVersion: '^18.0.0' },
'react-dom': { singleton: true, requiredVersion: '^18.0.0' },
},
}),
new HtmlWebpackPlugin({
template: './public/index.html',
}),
],
};
评论区