避免远程项目(remote)和主项目(host)的依赖重复加载,是微前端(MFE)架构中的核心优化之一。下面是结合 Angular + Webpack Module Federation 场景中的原理和具体配置方法。
node_modules
和依赖包。Webpack Module Federation 提供 shared
配置,声明哪些依赖是“共享”的,确保它们只加载一次。
shared
主应用和子应用的 webpack.config.js
中,都要声明共享依赖,通常是:
shared: {
'@angular/core': { singleton: true, strictVersion: true, requiredVersion: 'auto' },
'@angular/common': { singleton: true, strictVersion: true, requiredVersion: 'auto' },
'@angular/router': { singleton: true, strictVersion: true, requiredVersion: 'auto' },
'rxjs': { singleton: true, strictVersion: true, requiredVersion: 'auto' },
// 如果有其他公共依赖,也一并声明
}
package.json
读取版本号,保证主子应用版本一致。new ModuleFederationPlugin({
name: 'hostApp',
remotes: {
mfe1: 'mfe1@http://localhost:4201/remoteEntry.js',
},
shared: {
'@angular/core': { singleton: true, strictVersion: true, requiredVersion: 'auto' },
'@angular/common': { singleton: true, strictVersion: true, requiredVersion: 'auto' },
'@angular/router': { singleton: true, strictVersion: true, requiredVersion: 'auto' },
'rxjs': { singleton: true, strictVersion: true, requiredVersion: 'auto' },
},
});
new ModuleFederationPlugin({
name: 'mfe1',
filename: 'remoteEntry.js',
exposes: {
'./Module': './src/app/mfe1/mfe1.module.ts',
},
shared: {
'@angular/core': { singleton: true, strictVersion: true, requiredVersion: 'auto' },
'@angular/common': { singleton: true, strictVersion: true, requiredVersion: 'auto' },
'@angular/router': { singleton: true, strictVersion: true, requiredVersion: 'auto' },
'rxjs': { singleton: true, strictVersion: true, requiredVersion: 'auto' },
},
});
package.json
中依赖版本必须保持一致。npm ls rxjs
和 npm ls @angular/core
等命令确认依赖树。lodash
、moment
等通用库。strictVersion
配置。 strictVersion: false
并不能保证不重复加载依赖,它的作用主要是“放宽版本校验”,让共享依赖版本不严格匹配时依然能加载,但是否重复加载要看其他配置。
strictVersion
的作用strictVersion: true
:表示要求共享依赖的版本必须严格匹配 requiredVersion
,否则报错或不共享。
strictVersion: false
:允许版本不严格匹配,只要大致兼容就共享,避免因版本差异导致的冲突或错误。
singleton
singleton: true
是保证同一个共享模块全局只加载一份实例的关键配置。
只要设置了 singleton: true
,不管版本是否严格匹配,webpack 会尽量复用同一个版本。
strictVersion: false
的风险版本不严格匹配时会尝试共享,减少冲突报错,但如果主子应用依赖版本差异较大,运行时可能出现兼容性问题。
并不是“不重复加载”的保障,而是“版本冲突时更宽容”的配置。
配置项 | 是否保证不重复加载? | 作用 |
---|---|---|
singleton: true |
是 | 保证只加载一个共享实例 |
strictVersion: true |
否,版本不匹配会报错或失败共享 | 严格校验版本,保证兼容性 |
strictVersion: false |
否,宽松版本匹配,不保证兼容 | 避免因版本不符导致共享失败或报错 |
singleton: true
,保证共享依赖不会重复加载。strictVersion: true
,保持版本一致性,避免运行时问题。strictVersion: false
。关键点 | 说明 |
---|---|
shared 配置 | 通过 Module Federation 配置共享依赖 |
singleton: true | 保证依赖只加载一次 |
strictVersion: true | 严格版本控制,避免兼容问题 |
版本一致性 | 主子应用必须使用完全相同版本 |
自动版本获取 | requiredVersion: 'auto' |
strictVersion: false
,主应用是strictVersion: true会有什么影响呢?
如果主应用
strictVersion: true
,而子应用strictVersion: false
,这个共享依赖的最终加载行为由主应用决定,但 这种不一致的配置 会造成难以预料的兼容性和调试问题,建议主子项目的singleton
、strictVersion
、requiredVersion
配置 保持完全一致。
主项目设置 | 子项目设置 | 结果 / 影响 |
---|---|---|
strictVersion: true |
strictVersion: true |
✅ 推荐配置:主子应用必须版本完全一致,否则构建或运行时报错。 |
strictVersion: true |
strictVersion: false |
⚠️ 子应用不报错,但主项目会在版本不匹配时阻止共享,仍然会报错或共享失败。 |
strictVersion: false |
strictVersion: true |
⚠️ 主项目放松限制,可能共享了子应用不兼容的版本,导致运行时异常。 |
strictVersion: false |
strictVersion: false |
✅ 宽松配置:不会因为版本不一致而报错,但风险在于运行时版本冲突或行为不一致。 |
Webpack Module Federation 的共享模块解析是这样做的:
[email protected]
),它会注册为共享模块。rxjs
时,会比较自己的要求(requiredVersion
和 strictVersion
)是否接受这个已经加载的版本。如果主项目是 strictVersion: true
,要求加载的子模块版本 完全一致,但子项目用了 strictVersion: false
,它会默认“我能接受任何版本”,但主项目说“不行,我必须是这个版本”,于是冲突产生。
保持主项目和所有子项目的共享依赖配置一致:
shared: {
rxjs: {
singleton: true,
strictVersion: true,
requiredVersion: deps['rxjs'], // 或写死相同版本
}
}
这样可以:
在微前端架构里,主项目和子项目共享一个依赖(比如 rxjs
),但它们的版本号不一样,或者共享配置松散(strictVersion: false
),导致同一个模块可能被加载了多个不同版本,或者模块的内部状态不兼容。
[email protected]
,[email protected]
,后果:
rxjs
实例,内存占用翻倍;现象 | 说明 |
---|---|
多个版本同时加载 | 资源浪费,内存占用加倍 |
状态不一致 | 事件、订阅等核心功能异常 |
API 兼容性差导致崩溃 | 程序运行时报错,功能异常 |
难以调试 | 运行时错误不容易定位到版本冲突问题 |
singleton: true
,只加载一份实例。strictVersion: true
)。