Angular modules make it possible to consolidate components, directives, services, pipes, and many more into cohesive blocks of functionality. Angular's code is modularized. Every module has its own functionality. There are FormsModule, HttpModule, RouterModule, and many other modules as well. What does a module look like? A module is a class annotated with the @NgModule decorator (imported from @angular/core). @NgModule takes a configuration object that tells Angular how to compile and run the module code. The most significant properties of the the configuration object are:
- declarations: The array with components, directives, and pipes, which are implemented in that module and belong to that module.
- imports: The array with dependencies in form of other modules which need to be made available to that module.
- exports: The array of components, directives, and pipes to be exported and permitted to be imported by another modules. The rest is private. This is the module's public API and similar to how the export keyword works in ECMAScript modules.
- providers: This is the array of services (service classes, factories, or values), which are available in that module. Providers are parts of the module and can be injected into components (inclusive sub-components), directives, and pipes defined within the module.
- bootstrap: Every Angular application has at least one module--the root module. The bootstrap property is only used in the root module and contains the component which should be instantiated first when bootstrapping the application.
- entryComponents: This is the array of components that Angular generates component factories for. Normally, you need to register a component as an entry component when it is intended to be created dynamically at runtime. Such components can not be figured out automatically by Angular at template compilation time.
A typical module configuration for any separate example in this book looks something like this:
import {NgModule} from '@angular/core';
import {BrowserModule} from '@angular/platform-browser';
import {BrowserAnimationsModule} from '@angular/platform-browser/animations';
import {FormsModule} from '@angular/forms';
import {APP_BASE_HREF} from '@angular/common';
// PrimeNG modules needed in this example
import {ButtonModule} from 'primeng/components/button/button';
import {InputTextModule} from 'primeng/components/inputtext/inputtext';
import {AppComponent} from './app.component';
import {SectionComponent} from './section/section.component';
import {routes} from './app-routing.module';
@NgModule({
imports: [BrowserModule, BrowserAnimationsModule, FormsModule,
routes, ButtonModule, InputTextModule],
declarations: [AppComponent, SectionComponent],
providers: [{provide: APP_BASE_HREF, useValue: '/'}],
bootstrap: [AppComponent]
})
export class AppModule { }
The following is an example of how to bootstrap an Angular application in the JIT mode (just in time compilation):
import {platformBrowserDynamic} from '@angular/platform-browser-dynamic';
import {AppModule} from './app';
platformBrowserDynamic().bootstrapModule(AppModule);
In the ahead-of-time mode (AOT compilation), you need to provide a factory class. To generate the factory class, you must run the ngc compiler instead of the TypeScript tsc compiler. In the last two sections of this chapter, you will see how to use AOT with Webpack and Angular CLI. The bootstrapping code in the AOT mode looks like the following:
import {platformBrowser} from '@angular/platform-browser';
import {AppModuleNgFactory} from './app.ngfactory';
platformBrowser().bootstrapModuleFactory(AppModuleNgFactory);
Modules can also be lazy loaded when they get requested (on demand). This approach reduces the size of web resources loaded on initial page display. The page appears faster. If you want to enable lazy loading, you have to configure the router to load the module lazy. All you need is a path object with a loadChildren property, which points to the path and name of the lazy loaded module:
{path: "section", loadChildren: "app/section/section.module#SectionModule"}
Note that the value of loadChildren property is a string. Furthermore, the module importing this router configuration should not declare the lazy loaded module as dependency in the imports property of the configuration object.