Lazy Loading

En configurant l'intégralité du Routing de l'application dans le module AppRoutingModule, on serait amené à importer tous les modules de l'application avant son démarrage. A titre d'exemple, plus l'application sera riche, plus la page d'accueil sera lente à charger par effet de bord.

Pour éviter ces problèmes de "scalability", Angular permet de charger les modules à la demande (i.e. : "Lazy Loading") afin de ne pas gêner le chargement initial de l'application.

Configuration du Lazy Loading

La configuration du "Lazy Loading" se fait au niveau du "Routing".

Le module de "Routing" AppRoutingModule peut déléguer la gestion du "Routing" d'une partie de l'application à un autre module. Ce module "Lazy Loaded" sera donc chargé de façon asynchrone à la visite des "routes" dont il est en charge.

@NgModule({
    declarations: [
        AppComponent,
        LandingComponent
    ],
    imports: [
        AppRoutingModule,
        BrowserModule
    ],
    bootstrap: [AppComponent]
})
export class AppModule {
}
export const appRouteList: Routes = [
    {
        path: 'landing',
        component: LandingComponent
    },
    {
        path: 'book',
        loadChildren: './views/book/book-routing.module#BookRoutingModule'
    },
    {
        path: '**',
        redirectTo: 'landing'
    }
];

@NgModule({
    exports: [
        RouterModule
    ],
    imports: [
        HttpClientModule,
        RouterModule.forRoot(appRouteList)
    ]
})
export class AppRoutingModule {
}
export const bookRouteList: Routes = [
    {
        path: 'search',
        component: BookSearchComponent
    },
    {
        path: '**',
        redirectTo: 'search'
    }
];

@NgModule({
    imports: [
        BookModule,
        RouterModule.forChild(bookRouteList)
    ]
})
export class BookRoutingModule {
}

Cette configuration délègue le "Routing" de toute la partie /book/... de l'application au module BookRoutingModule.

Pour profiter du "Lazy Loading", assurez-vous que les modules "Lazy Loaded" ne sont jamais chargé explicitement ("Eagerly Loaded") !

Il faut donc épurer au maximum les imports d'AppModule.

La syntaxe loadChildren: './views/book/book-routing.module#BookRoutingModule' est un raccourci pour le chargement asynchrone de la classe BookRoutingModule :

loadChildren: () => import('./views/book/book-routing.module')
    .then(module => module.BookRoutingModule);

BookRoutingModule est à la fois un Routed Feature Module et un Routing Module.

Résultat du "build"

En analysant le résultat du "build" dans le dossier dist, on peut remarquer la création d'un nouveau fichier 0.9b8cc2f6fc3b76db8fd7.js. Il s'agit du "chunk" contenant le code associé à la "Routed Feature Module" BookRoutingModule.

Tant que BookModule n'est importé que par BookRoutingModule, tout le code associé à ce module sera inclus dans le même "chunk".

forRoot vs forChild

Seul le module AppRoutingModule importe le module RouterModule avec la méthode statique forRoot afin de définir le "Routing" racine et la configuration du router via le second paramètre.

Les "Child Routing Modules" importent le RouterModule avec la méthode forChild.

Preloading Strategy

Une fois l'application démarrée et pour éviter la latence de chargement des "Lazy Loaded Routes", il est possible de configurer le "Routing" pour précharger tous les modules "Lazy Loaded" juste après le démarrage de l'application.

RouterModule.forRoot(appRouteList, {
    preloadingStrategy: PreloadAllModules
})

Dernière mise à jour