View
297
Download
0
Category
Preview:
Citation preview
AngularChristoffer Noring
Google Developer ExpertFrontend Developer OVO Energy
@chris_noring
modules
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
angular.module(‘app’,[
])
Declare module
Declare constructs belonging to said module
.controller()
.directive()
.value()
.provider()
Declare dependant modules‘dep1’, ‘dep2’
Angular 1
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
@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
Angular ModulesCommonModul
e
ngIf
ngFor
imports and reexports
BrowserModule FormsModule
Directives and Components supporting template driven forms
ngModel
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 : []
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
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
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
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, ]
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
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
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
App architecture
AppModule
CoreModuleContactsModule ProductsModule CommonModule
Feature modules
FormsModule BrowserModule RouterModule
Angular core modules
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
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
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
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
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
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
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
@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
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
Thank you
@chris_noring
Recommended