Как использовать .forRoot() в иерархии функциональных модулей

Кто-нибудь может пояснить мне, как мне структурировать иерархию нескольких вложенных функциональных модулей с вызовами .forRoot()?

Например, если у меня есть такие модули:

- MainModule
- SharedModule
- FeatureModuleA
    - FeatureModuleA1
    - FeatureModuleA2
- FeatureModuleB

Все функциональные модули имеют статические функции .forRoot().

Как определить FeatureModuleA каким-то образом "передать" функции .forRoot()?

@NgModule({ 
  imports: [
    //- I can use .forRoot() calls here but this module not the root module
    //- I don't need to import sub-modules here, FeatureA only a wrapper
    //FeatureModuleA1.forRoot(), //WRONG!
    //FeatureModuleA2.forRoot(), //WRONG!
  ],
  exports: [
    //I cannot use .forRoot() calls here
    FeatureModuleA1, 
    FeatureModuleA2 
  ]
})
class FeatureModuleA {
  static forRoot(): ModuleWithProviders {
    return {
      //At this point I can set any other class than FeatureModuleA for root
      //So lets create a FeatureRootModuleA class: see below!
      ngModule: FeatureModuleA //should be: FeatureRootModuleA 
    };
  }
}

Я могу создать еще один класс для использования root, а затем установить его внутри функции forRoot() FeatureModuleA:

@NgModule({
  imports: [
    //Still don't need any sub module within this feature module
  ]
  exports: [
    //Still cannot use .forRoot() calls but still need to export them for root module too:
    FeatureModuleA1, 
    FeatureModuleA2 
  ]
})
class FeatureRootModuleA { }

Но как я могу "перевести" вызовы .forRoot() внутри этого специального ModuleClass?

Как я вижу, мне нужно импортировать все подмодули непосредственно в мой основной MainModule и вызывать .forRoot() для каждого из них:

@NgModule({
  imports: [
    FeatureModuleA1.forRoot(),
    FeatureModuleA2.forRoot(),
    FeatureModuleA.forRoot(),
    SharedModule.forRoot()
  ]
})
class MainModule { }

Я прав? Прежде чем ответить, пожалуйста, взгляните на этот файл: https://github.com/angular/material2/blob/master/src/lib/module.ts

Как я знаю, это репо поддерживается официальной командой angular. Поэтому они решают вышеупомянутое, просто импортируя все вызовы .forRoot() в специальном модуле MaterialRootModule. Я действительно не понимаю, как это будет применяться для моего собственного корневого модуля? Что действительно означает root и .forRoot? Это относительно пакета, а не фактического веб-проекта?

Ответ 1

Как правило, forRoot используется для добавления приложений/одиночных сервисов.

@NgModule({
  providers: [ /* DONT ADD HERE */ ]
})
class SharedModule {
  static forRoot() {
    return {
      ngModule: SharedModule,
      providers: [ AuthService ]
    }
  }
}

Причиной является то, что если вы добавите AuthService в providers в @NgModule, возможно создание более одного, если вы импортируете SharedModule в другие модули.

Я не на 100% не понимаю, будет ли создаваться служба, когда SharedModule импортируется в загружаемый модуль, но объяснение, о котором упоминалось в документах, относится к лениво загруженным модулям. Когда вы ленивно загружаете модуль, все провайдеры будут созданы.

По этой причине мы добавляем метод (по соглашению) forRoot для обозначения того, что метод должен вызываться только для корневого (app) модуля, тогда как для другого модуля его следует просто импортировать

@NgModule({
  imports: [SharedModule]
})
class FeatureModule {}

@NgModule({
  imports: [SharedModule.forRoot()]
})
class AppModule {}