A dynamically loaded module is an application feature whose code is excluded from the initial JavaScript download and fetched when navigation reaches its route. This reduces startup cost, especially on slow networks, but requires the feature to remain separate from the main application and to contain functionality that not every user needs. section 27.0 section 27.6
Configure the feature in two routing layers:
- Create a feature module with its component and use CommonModule rather than BrowserModule. section 27.3.1
- Define the feature’s internal routes with RouterModule.forChild; these routes merge into the application routes when the module loads. section 27.3.2
- Add a main-application route whose loadChildren function imports the module and selects its module class. section 27.3.2
- Navigate normally with routerLink; the URL activates the route and triggers loading without special navigation code. section 27.3.2
On-demand feature
An OndemandModule declares and exports OndemandComponent, imports CommonModule and child routing, and maps its empty path to the component. A main route loads it at /ondemand, while a Load Module button uses routerLink="/ondemand". section 27.3.1 section 27.3.2
Listing 27.5. Defining routes in the ondemand.module.ts file in the src/app/ondemand folder
import { NgModule } from "@angular/core";
import { CommonModule } from "@angular/common";
import { OndemandComponent } from "./ondemand.component";
import { RouterModule } from "@angular/router";
let routing = RouterModule.forChild([
{ path: "", component: OndemandComponent }
]);
@NgModule({
imports: [CommonModule, routing],
declarations: [OndemandComponent],
exports: [OndemandComponent]
})
export class OndemandModule { }
Inspect the complete feature-module routing configuration using RouterModule.forChild. section 27.3.2
Listing 27.6. Creating an on-demand route in the app.routing.ts file in the src/app folder
import { Routes, RouterModule, mapToResolve, mapToCanActivate,
mapToCanActivateChild, mapToCanDeactivate } from "@angular/router";
import { TableComponent } from "./core/table.component";
import { FormComponent } from "./core/form.component";
import { NotFoundComponent } from "./core/notFound.component";
import { ProductCountComponent } from "./core/productCount.component";
import { CategoryCountComponent } from "./core/categoryCount.component";
import { ModelResolver } from "./model/model.resolver";
import { TermsGuard } from "./terms.guard";
import { UnsavedGuard } from "./core/unsaved.guard";
const childRoutes: Routes = [
{ path: "",
canActivateChild: mapToCanActivateChild([TermsGuard]),
children: [{ path: "products", component: ProductCountComponent },
{ path: "categories",
component: CategoryCountComponent },
{ path: "", component: ProductCountComponent }],
resolve: { model: mapToResolve(ModelResolver) }
}
];
const routes: Routes = [
{
path: "ondemand",
loadChildren: () => import("./ondemand/ondemand.module")
.then(m => m.OndemandModule)
},
{
path: "form/:mode/:id", component: FormComponent,
resolve: { model: mapToResolve(ModelResolver) },
canDeactivate: mapToCanDeactivate([UnsavedGuard])
},
{
path: "form/:mode", component: FormComponent,
resolve: { model: ModelResolver },
canActivate: mapToCanActivate([TermsGuard])
},
{ path: "does", redirectTo: "/form/create", pathMatch: "prefix" },
{ path: "table", component: TableComponent, children: childRoutes },
{ path: "table/:category", component: TableComponent,
children: childRoutes },
{ path: "", redirectTo: "/table", pathMatch: "full" },
{ path: "**", component: NotFoundComponent }]
export const routing = RouterModule.forRoot(routes, {
bindToComponentInputs: true
});
Inspect the application-level route that supplies the dynamically imported module location. section 27.3.2
