Angular modules in depth

25
Angular Christoffer Noring Google Developer Expert Frontend Developer OVO Energy @chris_noring modules

Transcript of Angular modules in depth

Page 1: Angular modules in depth

AngularChristoffer Noring

Google Developer ExpertFrontend Developer OVO Energy

@chris_noring

modules

Page 2: Angular modules in depth

Helps organize an application into cohesive blocks of functionality

Decorates class with @NgModule

Angular libs that are modulesFormsModule, HttpModule, RouterModule

Third party libsMaterial Design, AngularFire, Ionic

Can be lazy loadedCan be eagerly loaded

Page 3: Angular modules in depth

angular.module(‘app’,[

])

Declare module

Declare constructs belonging to said module

.controller()

.directive()

.value()

.provider()

Declare dependant modules‘dep1’, ‘dep2’

Angular 1

Page 4: Angular modules in depth

Service - singletonWe care about state

export class Service { getData(){ }}

@injectable()

Declareimport { Service } from ‘services/service’;

export class SomeComponent{

constructor( private srv:Service, private other:OtherService){

}

doStuff(){ var data = this.srv.getData(); }}

Consume

Don’t forget @injectable keyword

Inject as usual

Use

Page 5: Angular modules in depth

@NgModule({ imports : [ BrowserModule ], declarations : [ AppComponent, SomeComponent, SomePipe, SomeDirective ] bootstrap : [ AppComponent ], providers : [ serviceForThisModule ], entryComponents : [] })export class AppModule{

}

A2 - Module anatomyDependant modules

Constructs the module consist of

Entry point of the app

Injectable services

Page 6: Angular modules in depth

Angular ModulesCommonModul

e

ngIf

ngFor

imports and reexports

BrowserModule FormsModule

Directives and Components supporting template driven forms

ngModel

Page 7: Angular modules in depth

Root ModuleA module to launch the app

@NgModule({ imports : [ BrowserModule, FeatureModule, CommonModule ], declarations : [ AppComponent, SomeComponent, SomePipe, SomeDirective ] bootstrap : [ AppComponent ], providers : [ serviceForThisModule ] })export class AppModule{

}

All other modules your app consist of is listed in the imports :[]

The entry component is pointed out in the bootstrap : []

Page 8: Angular modules in depth

BootstrappingWith JIT

With AOT

import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';import { AppModule } from './app.module';

import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';import { AppModuleNgFactory } from ‘./app.module.ngfactory';

platformBrowserDynamic().bootstrapModule(AppModuleNgFactory);

platformBrowserDynamic().bootstrapModule(AppModule);

Root module

Page 9: Angular modules in depth

Feature Module@NgModule({ imports : [ FormsModule, CommonModule ], declarations : [ FeatureComponent, SomeOtherComponent, FeaturePipe, FeatureDirective ] exports : [ CommonComponent ], providers : [ serviceForThisModule ] })export class FeatureModule{

}

Dependant modules

Component/constructs the module consists of

Publicly usable constructs

A module to extend the app

Page 10: Angular modules in depth

ImportAllows us to use constructs from other modules such as

DirectivesPipesComponents

But only that which is public

imports : [ SomeModule ],exports : [ FeatureComponent ]

FeatureModuleSomeModuleimports : [ ],exports : [ SomeComponent, SomeDirective] Can be used in

FeatureComponent markup

Page 11: Angular modules in depth

ExportingA normal feature module would only export the top component

ProductDetailComponent

ProductAdvertisementComponent

This would not be exported as they are helper components

ProductListComponent This would be exported

exports : [ ProductListComponent, ]

Page 12: Angular modules in depth

Re exportReexport is making constructs from other modules available

imports : [ ],exports : [ SomeModule, FeatureComponent ]

FeatureModule

make public SomeModule constructs available for importers of FeatureModule

Example from angular BrowserModule reexports CommonModule, ApplicationModule

SomeModuleimports : [ ],exports : [ SomeComponent, SomeDirective]

public

ParentModuleimports

Page 13: Angular modules in depth

When not to re-export

Module

Service1

Service2

Service3

When there is no construct such as directive, pipes or components but only services

example HttpModule

Page 14: Angular modules in depth

SharedModulewhat to export

HelperComponent

CommonComponent CommonDirective

MoneyPipe FilteringPipe

Most constructs would likely be exported

exports : [ CommonComponent, CommonDirective, MoneyPipe, FilteringPipe ]

Majority is exported, minority not exported

Page 15: Angular modules in depth

App architecture

AppModule

CoreModuleContactsModule ProductsModule CommonModule

Feature modules

FormsModule BrowserModule RouterModule

Angular core modules

Page 16: Angular modules in depth

Core ModuleFor application wide services, places them in a core module

This ensures they are singletons

@NgModule({ imports : [ … ], declarations : [ CoreComponent.. ] exports : [ CommonComponent ], providers : [ applicationWideService, applicationWideService2 ] })export class CoreModule{

}

CoreModule

Services

Import only from AppModule

@NgModule({ imports : [ CoreModule ], declarations : [ AppComponent ] bootstrap : [ AppComponent ], providers : [ ] })export class AppModule{

}

AppModule

Page 17: Angular modules in depth

Providers

Application scoped by design

A certain service can be injected in any construct

Providers listed in @NgModule.providers have application scope

When a module is imported the modules providers list is added root injector

@NgModule({ imports : [ SomeModule ], declarations : [ SomeComponent ] exports : [ SomeComponent ], providers : [ service1, service2, service3 ] })export class SomeModule{

}

root injecto

r

Page 18: Angular modules in depth

Word of cautionImport modules with providers only onceProvide the service in a component if component needs its own copy, but generally add it to the module’s providers

Try to lazy load modules as much as possible, they get their own injector

aka providers overridden by mistake

App-wide providers should be added to AppModule not AppComponent if you have lazy loaded modules

Import HttpModule only in AppModule to avoid provider corruption SomeModul

eHttpModule

OtherModule

HttpModuleproviders providers

configuration done in one provider might be lost

Page 19: Angular modules in depth

Lazy loadapp.routing.tsconst routes: Routes = [ { path: '', redirectTo: '/home', pathMatch: 'full', { path: 'about', loadChildren: './+about/about.module#AboutModule' }];

#AboutModule Name of module+ Naming convention of lazy loaded modules

./+about/about.routing.tsconst routes: Routes = [ { path: '', component: AboutComponent },];

File Module class

Page 20: Angular modules in depth

Don’t place services in a shared module,

there would be one instance per lazy loaded module

different instances

Feature Module

Shared Module

lazy loaded

Service1:instance1

imports

Feature Module

Shared Module

lazy loaded

Service1:instance2

imports

constructor(service1:Service1) {}

Shared Module

Service1 Service2 Service3

Page 21: Angular modules in depth

Prevent reimport of core module

CoreModule

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

Throw error if someone but root module imports me

Don’t let my own injector instantiate me

AppModule

CoreModuleimports

FeatureModule

CoreModuleimports

Page 22: Angular modules in depth

RefactorLets take an existing app and divide in suitable modules

Looks like feature component

Looks like feature serviceLooks like an application wide service

Lets refactor

Looks like a reusable construct

@NgModule({ imports : [ BrowserModule ], declarations : [ AppComponent, AboutComponent, MoneyPipe ] bootstrap : [ AppComponent ], providers : [ AboutService, AuthService ] })

AppModule

Page 23: Angular modules in depth

@NgModule({ imports : [ AboutModule, CoreModule ], declarations : [ AppComponent, ] bootstrap : [ AppComponent ], providers : [ ] })

AppModule

@NgModule({ imports : [ SharedModule ], declarations : [ AboutComponent, ] bootstrap : [ AppComponent ], providers : [ AboutService ] })

AboutModule

AboutModule (Feature)AboutCompone

ntAboutService

1

SharedModuleMoneyPipe2

CoreModuleAuthService3

4

5

imports BrowserModule 5

Page 24: Angular modules in depth

SummaryComponents, Directives and Pipesare module scoped

Unless exported with exports keyword

Services listed in module providers is application wide

Divide up your app in suitable modules

Only have application wide services in a core modulethat is imported by the AppModule

Have shared constructs in shared modules but don't have providers in there on module level

Modules can make its constructs public by exposing it under exports keyword

Only the root module has the bootstrap keyword

Page 25: Angular modules in depth

Thank you

@chris_noring