liveBook · Manning

Dynamically loaded module

As explained in Pro Angular 16

A dynamically loaded module is an application module whose code is loaded on demand when navigation reaches a route that requires it.

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

How Pro Angular 16 covers it

How deep it goes
Explains module structure, separated routing configurations, dynamic imports, navigation, and dependency pitfalls without descending into loader internals.
Examples
Uses an OndemandComponent, OndemandModule, /ondemand route, and Load Module button to demonstrate deferred feature loading.
What it assumes
Assumes familiarity with Angular modules and routing while refreshing feature-module imports, child routes, and routerLink navigation.
What you can do after
Operate/configure Angular routing to separate a feature module and load it on demand through a navigable URL.
How it connects
Connects Angular routing, feature modules, dynamic imports, route guards, child routes, server-side rendering, and prerendering.

Related concepts

This explainer was generated by Manning's knowledge graph from the text of Pro Angular 16. The section links point to the parts of the book it draws on.