前回のスタイルガイドに続き、ドキュメント読んで気になる箇所を抜粋。
- NgModules
- Angular modularity
- The root AppModule
- Bootstrapping in main.ts
- Declare directives and components
- Service providers
- Import supporting modules
- Resolve directive conflicts
- Feature modules
- Lazy-loading modules with the router
- Shared modules
- The Core module
- Cleanup
- Configure core services with CoreModule.forRoot
- Prevent reimport of the CoreModule
- Conclusion
NgModules
- NgModuleのコンセプトをチュートリアル形式で説明したもの
Angular modularity
@NgModule
のmetadata- モジュールクラスは必ず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されるCommonModule
はngIf
,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
を返す
- serviceの設定オブジェクトを受け取り、
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'); } }