NgModulesのドキュメント読む

前回のスタイルガイドに続き、ドキュメント読んで気になる箇所を抜粋。

NgModules

Angular modularity

  • @NgModuleのmetadata
    • components, directives, pipesの宣言
    • 必要ならば、宣言したものをpublicにする (他のモジュールのテンプレートで利用可能になる)
    • 自身で必要な他のモジュールをインポートする
    • servicesを提供し、どのコンポーネントでも利用可能する
  • モジュールクラスは必ず1つある (root module)

The root AppModule

Bootstrapping in main.ts

Declare directives and components

Service providers

Modules are a great way to provide services for all of the module’s components.

The Dependency Injection page describes the Angular hierarchical dependency-injection system and how to configure that system with providers at different levels of the application’s component tree.

Dependency Injectionも後で読む)

  • モジュールはアプリケーションのroot dependency injectorにprovidersを追加し、servicesをアプリケーションのどこからでも利用可能にする

Import supporting modules

  • BrowserModuleをimportするとCommonModuleもimportされる
  • CommonModulengIf, ngForなどを宣言している

Application-scoped providers

  • serviceをmoduleに登録すると application-scoped になる (どこからでもinjectできるようになる)
  • アーキテクチャ的にはContactServiceは他のドメインで利用することはないので、injectできないようにしたい
  • Angularは意図的に module-scoping mechanism を提供していない

Read more in the How do I restrict service scope to a module? section of the NgModule FAQs page.

Resolve directive conflicts

Feature modules

  • モジュールは他のモジュールで宣言されているcomponents, directives, またはpipesへのアクセスを継承しない

Lazy-loading modules with the router

src/app/app-routing.module.ts

export const routes: Routes = [
  { path: '', redirectTo: 'contact', pathMatch: 'full'},
  { path: 'crisis', loadChildren: 'app/crisis/crisis.module#CrisisModule' },
  { path: 'heroes', loadChildren: 'app/hero/hero.module#HeroModule' }
];
  • routerについてはRouting & Navigation
  • cotact routeは Contact featureのrouting moduleで設定
  • routerによりContactComponentに遷移する場合、publicにする必要はない (exportする必要はない)
    • ContactComponentはselectorも必要としない

Shared modules

src/app/src/app/shared/shared.module.ts

@NgModule({
  imports:      [ CommonModule ],
  declarations: [ AwesomePipe, HighlightDirective ],
  exports:      [ AwesomePipe, HighlightDirective,
  
    // re-exports the CommonModule and FormsModule
    CommonModule, FormsModule ]
})
  • SharedModuleをimportすればCommonModule, FormsModuleもimportされるようになる
    • CommonModuleがimportされているのは、SharedModuleが必要としているから

Do not specify app-wide singleton providers in a shared module. A lazy-loaded module that imports that shared module makes its own copy of the service.

The Core module

  • CoreModuleは一度だけimportされる
    • AppRoot moduleがimportする

Cleanup

Configure core services with CoreModule.forRoot

  • 慣例で、forRootのstatic methodはserviceの提供と設定を同時に実行する
    • serviceの設定オブジェクトを受け取り、ModuleWithProvidersを返す

More precisely, Angular accumulates all imported providers before appending the items listed in @NgModule.providers. This sequence ensures that whatever you add explicitly to the AppModule providers takes precedence over the providers of imported modules.

src/app/core/user.service.ts (constructor)

constructor(@Optional() config: UserServiceConfig) {
  if (config) { this._userName = config.userName; }
}

src/app/core/core.module.ts (forRoot)

static forRoot(config: UserServiceConfig): ModuleWithProviders {
  return {
    ngModule: CoreModule,
    providers: [
      {provide: UserServiceConfig, useValue: config }
    ]
  };
}

src/app//app.module.ts (imports)

imports: [
  BrowserModule,
  ContactModule,
  CoreModule.forRoot({userName: 'Miss Marple'}),
  AppRoutingModule
],

Prevent reimport of the CoreModule

src/app/core/core.module.ts

constructor (@Optional() @SkipSelf() parentModule: CoreModule) {
  if (parentModule) {
    throw new Error(
      'CoreModule is already loaded. Import it in the AppModule only');
  }
}

Conclusion