我们当前遇到一个问题,我们想动态创建模块(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导入单个分发包文件并返回导出的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
是InjectionToken
,而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作为一个捆绑包提供,集成应用程序应将其加载并安装到应用程序中。