我们目前有一个问题,我们想动态创建一个模块(moduleFactory.create(this.injector))
。但是动态创建的模块的注入器没有父注入器的提供者。我们希望在我们的集成/主应用程序(创建子模块的地方)中实现一些核心内容,将其放入根注入器中,并希望通过 DI 将其放入我们的子模块和组件中(通过注入器,它是用主应用程序的注入器作为父级)。
我们基于这个例子的实现:https ://stackblitz.com/edit/angular-ifs7sp?file=src%2Fapp%2Flazy-loader.service.ts
const subsystems = await this.fetchSubsystems()
const promises = subsystems
.map(async (subsystem) => await subsystem.load())
const subsystemModuleFactories = await Promise.all(promisses)
subsystemModuleFactories.map(async (ngModuleOrNgModuleFactory) => {
let moduleFactory: NgModuleFactory<any>
if (ngModuleOrNgModuleFactory instanceof NgModuleFactory) {
moduleFactory = ngModuleOrNgModuleFactory
} else {
const compiler = this.injector.get(Compiler)
moduleFactory = await compiler.compileModuleAsync(ngModuleOrNgModuleFactory)
}
const entryComponent = (<any>moduleFactory.moduleType).entry
const moduleRef = moduleFactory.create(this.injector) // create the module ref with the injector of the main app as parent of the subsystem module
// Here we can still get the instance console.log(moduleRef.injector.get(I18n))
const compFactory = moduleRef.componentFactoryResolver.resolveComponentFactory(entryComponent)
container.createComponent(compFactory)
})
简而言之就是使用fetchSubsystems
SystemJS 导入单个 bundle 文件并返回导出的 AppModule:
SystemJS.import('subsystem') // mapped to an actual URL
.then((m) => (m as any).AppModule)
在子系统中我们要使用该服务:
export class AppComponent {
public constructor (@Inject(I18n) private i18n: II18n) {
}
}
I18n
isInjectionToken
和II18n
定义了服务的接口:
import { InjectionToken } from '@angular/core'
export interface II18n {
tr(key: string): string
}
export const I18n = new InjectionToken<II18n>('I18n')
不幸的是,我们得到了一个错误,即注入器中没有这样的 InjectionToken:
ERROR Error: Uncaught (in promise): NullInjectorError: StaticInjectorError(AppModule)[AppComponent -> InjectionToken I18n]:
StaticInjectorError(Platform: core)[AppComponent -> InjectionToken I18n]:
NullInjectorError: No provider for InjectionToken I18n!
NullInjectorError: StaticInjectorError(AppModule)[AppComponent -> InjectionToken I18n]:
StaticInjectorError(Platform: core)[AppComponent -> InjectionToken I18n]:
NullInjectorError: No provider for InjectionToken I18n!
at NullInjector.get (core.js:778)
at resolveToken (core.js:2564)
at tryResolveToken (core.js:2490)
at StaticInjector.get (core.js:2353)
at resolveToken (core.js:2564)
at tryResolveToken (core.js:2490)
at StaticInjector.get (core.js:2353)
at resolveNgModuleDep (core.js:26403)
at NgModuleRef_.get (core.js:27491)
at resolveNgModuleDep (core.js:26403)
at resolvePromise (zone-evergreen.js:797)
...
表达我们的意图(如果有更好的解决方案,我们还没有找到):我们想要一个类似“微前端”的东西。我们希望有一个集成或主应用程序,它提供核心应用程序和应用程序的基本布局。我们有多个“子系统”,即为特定业务逻辑提供 GUI 的小应用程序(是的,一种经典的微服务架构)。所以根据这个,在构建子系统的时候,GUI就已经构建好了。子系统将 GUI 作为单个包提供,集成应用程序应加载该包并将其安装到应用程序中。