Angular微前端(Module Federation)共享库/服务单例实现问题
我有一个Angular单体仓库工作区,使用@angular-architects/module-federation 14.13.14搭建POC。想要让本地共享库lib1里的BehaviorSubject服务在shell和app1两个微前端中以单例运行,但修改shell中服务的值后,app1无法同步更新。已经配置了tsconfig.json的路径映射,尝试过sharedMappings配置、手动在webpack.config.js中设置shared为单例等操作,都没解决问题,请问哪里操作有误?
工作区结构
Workspace |- Projects |- shell |- app1 |- lib1 |- service |- name: BehaviorSubject<string>
相关配置代码
tsconfig.json路径映射
"paths": { "lib1": [ "projects/lib1/src/public-api.ts" ] },
shell的webpack.config.js(含尝试的配置)
const { shareAll, share, withModuleFederationPlugin } = require('@angular-architects/module-federation/webpack'); module.exports = withModuleFederationPlugin({ shared: { ...shareAll({ singleton: true, strictVersion: true, requiredVersion: 'auto' }), }, // sharedMappings: ['lib1'], // 试过取消注释但没用 }, });
手动配置的shared
shared: share({ "@angular/core": { singleton: true, strictVersion: true, requiredVersion: "auto", }, "@angular/common": { singleton: true, strictVersion: true, requiredVersion: "auto", }, "@angular/common/http": { singleton: true, strictVersion: true, requiredVersion: "auto", }, "@angular/router": { singleton: true, strictVersion: true, requiredVersion: "auto", }, "lib1": { singleton: true, import: "../lib1/src/public-api.ts" }, "rxjs": { singleton: true, requiredVersion: "auto" } })
以下是可能的错误点和修复步骤:
确保所有微前端同步配置共享lib1
仅在shell中配置lib1的共享是不够的,必须在app1的webpack.config.js中做完全一致的共享配置(包括singleton: true)。如果app1没有同步配置,会自行打包一份lib1的副本,导致服务无法成为跨应用的单例。正确使用SharedMappings
若要通过sharedMappings实现共享,需要完成以下步骤:- 安装对应版本的
@angular-architects/module-federation-tools - 在所有微前端的webpack.config.js中正确初始化SharedMappings,确保路径指向根目录的tsconfig.json:
const { SharedMappings } = require('@angular-architects/module-federation-tools'); const path = require('path'); module.exports = withModuleFederationPlugin({ shared: shareAll({ singleton: true, strictVersion: true, requiredVersion: 'auto' }), sharedMappings: new SharedMappings().register( path.join(__dirname, '../../tsconfig.json'), ['lib1'] ) });
- 安装对应版本的
检查lib1服务的注入方式
确保lib1中的服务使用providedIn: 'root'声明,让Angular将其注册为根级单例:@Injectable({ providedIn: 'root' }) export class YourService { name = new BehaviorSubject<string>('initial value'); }如果是通过模块的providers数组声明服务,要使用
forRoot()模式确保仅在shell中初始化一次,其他微前端通过forChild()导入。修正手动共享配置的路径
手动配置shared时,lib1的导入路径应使用tsconfig中定义的别名,而非相对路径,避免不同应用解析路径不一致:"lib1": { singleton: true, import: 'lib1', requiredVersion: 'auto' }同时保证所有微前端的shared配置参数(
singleton、strictVersion等)完全一致。清理缓存并重启服务
webpack缓存可能导致旧模块残留,执行以下操作:- 删除所有微前端的
dist目录 - 清除npm缓存(可选:
npm cache clean --force) - 重启所有微前端的开发服务
- 删除所有微前端的
内容的提问来源于stack exchange,提问作者thiagopg84

