使用 Webpack 5 的 Module Federation
使用 Webpack Module Federation 配置宿主应用和远程应用,以便在运行时共享组件。
使用 Webpack 5 的 Module Federation 是 CoddyKit 上的免费 React Academy 课时。 这是第 2 节课,共 4 节。 你可以在下方免费阅读本课时的完整内容 — 然后在浏览器中使用内置代码编辑器和全天候 AI 导师进行实践。 这是 React Academy 学习路径的一部分,你的进度在网页和 CoddyKit 应用中同步。 React Academy 课程共包含 4 节课。
模块联邦概览
Webpack 5 的模块联邦允许您在运行时在分别打包的应用之间共享 JavaScript 模块——一个应用暴露组件,另一个应用无需构建步骤即可使用这些组件。
角色:主应用与远程应用
一个远程应用会暴露模块。一个主应用会使用一个或多个远程应用中的模块。同一个应用可以同时充当主应用和远程应用。
远程应用配置
在远程应用的 webpack.config.js 中,使用 ModuleFederationPlugin 暴露组件。
// Remote: apps/products/webpack.config.js
const { ModuleFederationPlugin } = require('webpack').container;
module.exports = {
plugins: [
new ModuleFederationPlugin({
name: 'products', // remote name
filename: 'remoteEntry.js', // entry file
exposes: {
'./ProductCard': './src/components/ProductCard', // exposed module
'./CartButton': './src/components/CartButton',
},
shared: ['react', 'react-dom'], // share deps to avoid duplication
}),
],
};主应用配置
在主应用的 webpack 配置中,声明要使用哪些远程应用,以及从哪里加载它们。
// Host: apps/shell/webpack.config.js
new ModuleFederationPlugin({
name: 'shell',
remotes: {
products: 'products@http://localhost:3001/remoteEntry.js',
cart: 'cart@http://localhost:3002/remoteEntry.js',
},
shared: ['react', 'react-dom'],
})使用远程模块
使用远程应用名称作为路径前缀来导入远程模块。将它们包裹在 React.lazy 和 Suspense 中,以实现延迟加载。
import React, { lazy, Suspense } from 'react';
const ProductCard = lazy(() => import('products/ProductCard'));
function App() {
return (
<Suspense fallback={<div>Loading...</div>}>
<ProductCard productId="123" />
</Suspense>
);
}共享依赖
使用 singleton: true 列出共享软件包,以确保所有微前端只加载一份 React。
shared: {
react: { singleton: true, requiredVersion: '^18.0.0' },
'react-dom': { singleton: true, requiredVersion: '^18.0.0' },
'@company/design-system': { singleton: true },
},动态远程应用
在运行时从配置(例如清单端点)动态加载远程应用,而不是将 URL 硬编码在 webpack 配置中。
async function loadRemote(scope, module) {
await __webpack_init_sharing__('default');
const container = window[scope];
await container.init(__webpack_share_scopes__.default);
const factory = await container.get(module);
return factory();
}
const ProductCard = React.lazy(() => loadRemote('products', './ProductCard'));使用 TypeScript 配合模块联邦
使用 @module-federation/typescript 插件为暴露的模块生成类型声明,以便主应用获得完整的自动补全功能。
远程应用故障的错误边界
将远程组件包裹在错误边界中。如果远程应用加载失败,主应用可以优雅降级,而不是崩溃。
<ErrorBoundary fallback={<div>Product unavailable</div>}>
<Suspense fallback={<Skeleton />}>
<ProductCard productId={id} />
</Suspense>
</ErrorBoundary>Vite 模块联邦
@originjs/vite-plugin-federation 插件以相似的 API 将模块联邦引入基于 Vite 的项目。
// vite.config.ts (remote)
import federation from '@originjs/vite-plugin-federation';
export default defineConfig({
plugins: [
federation({
name: 'products',
filename: 'remoteEntry.js',
exposes: { './ProductCard': './src/ProductCard' },
shared: ['react'],
}),
],
});快速检查
在模块联邦中为共享软件包设置 singleton: true 有什么作用?
回顾
模块联邦在远程应用中使用 ModuleFederationPlugin 来暴露模块,在主应用中使用它来使用模块。使用 lazy() 导入远程模块,将 react 作为单例共享以避免重复,并将远程应用包裹在错误边界中以实现优雅降级。
常见问题解答
「使用 Webpack 5 的 Module Federation」课时是免费的吗?
是的 — 「使用 Webpack 5 的 Module Federation」的完整文本可在网页上免费阅读。要进行交互式练习(内置代码编辑器和全天候 AI 导师)并解锁 React Academy 课程的其余内容,请升级到 CoddyKit PRO。 React Academy 课程共包含 4 节课。
「使用 Webpack 5 的 Module Federation」这节课中我会学到什么?
使用 Webpack Module Federation 配置宿主应用和远程应用,以便在运行时共享组件。 你通过在浏览器中直接运行的动手代码来练习 React Academy,全天候 AI 导师会在你学习这节课的过程中回答你的问题。
学习 React Academy 需要有经验吗?
无需任何先前经验。CoddyKit 上的 React Academy 课程适合初学者到高级学习者,你可以从这里开始或从头开始,按照自己的节奏学习。 这是第 2 节课,共 4 节。
「使用 Webpack 5 的 Module Federation」课时需要多长时间?
大多数 CoddyKit 课程大约需要 5–10 分钟。每节课都很精短且互动,所以你能稳步进步,并在网页和应用中从离开的地方继续。
我能在这节 React Academy 课中编写并运行代码吗?
能。每节 React Academy 课都包含内置代码编辑器,你可以在浏览器中直接编写并运行真实代码,并获得即时 AI 反馈 — 无需本地设置。
此课程中的所有课时
- 微前端概念与权衡
- 使用 Webpack 5 的 Module Federation
- MFE 之间的共享状态与路由
- MFE 的独立部署与 CI 流水线