Appearance
第11章 Module Federation 2.0 与 Rspack
"模块联邦的第一个版本证明了跨构建产物共享代码是可行的——而第二个版本证明了这件事可以变得简单、安全、且极其快速。"
本章要点
- 理解 Module Federation 2.0 相比 1.0 的三大飞跃:类型安全、运行时插件系统、动态远程加载
- 掌握 Rspack 中 Module Federation 的配置与 Rust 编译带来的性能优势
- 深入 @module-federation/enhanced 运行时核心源码,理解模块加载与版本协商的底层机制
- 实现跨框架(React + Vue)的 Module Federation 实践方案
- 建立 MF 2.0 在生产环境的部署策略:版本管理、灰度发布、容灾降级
2022 年底的一个深夜,我正在调试一个 Webpack 5 Module Federation 的线上问题。远程模块加载失败了,但错误信息只有一行冷冰冰的 ScriptExternalLoadError。没有类型提示告诉我远程模块的接口长什么样,没有运行时钩子让我在加载失败时做降级处理,甚至无法在不重新部署宿主应用的情况下切换远程模块的地址。
我花了四个小时定位问题——最终发现是远程应用的一次接口变更导致类型不匹配,而宿主应用在编译期对此一无所知。
这就是 Module Federation 1.0 的困境:它打开了一扇通往跨应用模块共享的大门,却没有在门口放一盏灯。
2024 年,Zack Jackson 和团队发布了 Module Federation 2.0。这不是一次小版本迭代,而是一次架构级的重构。类型安全、运行时插件、动态远程、跨构建工具支持——这些能力让 Module Federation 从"能用"进化到"好用"。而 Rspack 的加入,则让"好用"变成了"飞快"。
本章将带你完整走过这条进化之路。
下图展示了 Module Federation 从 1.0 到 2.0 的架构跃迁,以及 Rspack 带来的编译性能提升:
11.1 MF 2.0 的新能力
Module Federation 1.0 解决了一个根本问题:如何在运行时从另一个独立部署的应用中加载模块。但它留下了三个关键缺口——类型安全、运行时扩展性、动态远程管理。MF 2.0 逐一填补了这些缺口。
11.1.1 类型安全:@module-federation/typescript
在 MF 1.0 中,远程模块对宿主应用而言是一个黑盒。你通过字符串引用一个远程模块,TypeScript 编译器对它的类型一无所知。MF 2.0 通过 @module-federation/typescript 引入了完整的类型安全机制——远程应用在构建时生成类型声明,宿主应用在开发时自动拉取。
typescript
// remote-app/rspack.config.ts(远程应用配置)
import { ModuleFederationPlugin } from '@module-federation/enhanced/rspack';
export default {
plugins: [
new ModuleFederationPlugin({
name: 'remoteApp',
filename: 'remoteEntry.js',
exposes: {
'./Button': './src/components/Button.tsx',
'./UserCard': './src/components/UserCard.tsx',
'./useAuth': './src/hooks/useAuth.ts',
},
dts: {
generateTypes: {
extractRemoteTypes: true,
compileInChildProcess: true,
},
},
shared: {
react: { singleton: true, requiredVersion: '^18.0.0' },
'react-dom': { singleton: true, requiredVersion: '^18.0.0' },
},
}),
],
};宿主应用的配置负责消费这些类型:
typescript
// host-app/rspack.config.ts(宿主应用配置)
import { ModuleFederationPlugin } from '@module-federation/enhanced/rspack';
export default {
plugins: [
new ModuleFederationPlugin({
name: 'hostApp',
remotes: {
remoteApp: 'remoteApp@http://localhost:3001/remoteEntry.js',
},
dts: {
consumeTypes: {
remoteTypesFolder: '@mf-types',
abortOnError: false,
consumeAPITypes: true,
},
},
shared: {
react: { singleton: true, requiredVersion: '^18.0.0' },
'react-dom': { singleton: true, requiredVersion: '^18.0.0' },
},
}),
],
};配置完成后,宿主应用引用远程模块时便获得了完整的类型推导:
typescript
// host-app/src/App.tsx —— 完整的类型推导
import RemoteButton from 'remoteApp/Button';
import { useAuth } from 'remoteApp/useAuth';
function App() {
const { user, login, logout } = useAuth(); // ✅ 完整的类型推导
return (
<RemoteButton
label="登录" // ✅ string 类型
onClick={login} // ✅ () => void
variant="primary" // ✅ 联合类型自动补全
// color={123} // ❌ 编译期报错:不存在属性 'color'
/>
);
}类型同步的底层使用 TypeScript Compiler API 提取暴露模块的声明文件,打包为可下载归档,宿主应用开发时从远程拉取并解压到 node_modules/@mf-types/ 目录,最后生成 TypeScript path mapping。
💡 深度洞察:MF 2.0 的类型安全不仅仅是"开发体验的提升"。在微前端架构中,远程模块的接口变更是最常见的故障来源之一。类型系统将这类问题从"运行时崩溃"前移到"编译期报错"。在传统微服务架构中,API 契约通过 OpenAPI/Protobuf 来保障;而在微前端架构中,模块联邦的类型系统扮演的正是同样的角色。
11.1.2 运行时插件系统
下图展示了 MF 2.0 运行时插件系统的钩子执行流程,每个阶段都可以被插件拦截和扩展: