5

我们目前有一个问题,我们想动态创建一个模块(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)
})

简而言之就是使用fetchSubsystemsSystemJS 导入单个 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) {
  }
}

I18nisInjectionTokenII18n定义了服务的接口:

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 作为单个包提供,集成应用程序应加载该包并将其安装到应用程序中。

4

0 回答 0