In this lesson, we are going to cover:
- Lazy Loading of Feature Modules
- And Creating Preloading Strategy for Lazy-Loaded Modules
Prerequisite
Lazy Loading Feature Modules
To use lazy loading, first, you need to create some feature modules. Feature modules are NgModules created for the purpose of code organization. Feature modules allow you to separate code for a feature/functionality from the rest of your app. Components, Pipes, Directives, etc. inside a feature module are isolated from the rest of your app and are only accessible inside the feature module.
To create feature modules, we have two option – a manual approach and automated approach.
Manual Approach
In this approach, we are going to do everything ourselves. First, we are going to use Angular CLI command ng generate module
to generate a feature module. Please note, for the purpose of lazy loading, our module needs to have routing enabled. We can do this by using the --routing
flag, as shown below:
ng generate module lazyloadedmodule1 --routing
The above command is going to create a Lazymodule1Module
and Lazymodule1RoutingModule
. Where the first is the NgModule
and the second is the routing module where routes for our feature module will live.
Secondly, we will need some components or directives or pipes, etc. for our feature module. The simplest approach is to put components/directives/pipes inside the same directory as our feature module or its sub-directories. This way, they will be registered under our feature module. You can also use the --module
flag if you want your feature module and its related assets to live in separate directories.
And finally, we need to add the feature module inside our app router module, as shown below:
{
path: 'lazy-module-1',
loadChildren: () =>
import('./lazymodule1/lazymodule1.module').then(m => m.Lazymodule1Module)
}
Automated Approach
As of Angular 8, you can generate a feature module with routing enabled, a default component and add as a lazy loaded route to the router.
ng generate module lazymodulename --module app --route lazy-module-route
The above command must have the following flags:
--module
flag (Required) – The module where to register the route for the app.--route
flag (Required) - The path for your lazy module route.
If any of the above flags are missing, it will fail.
NB: You can use the
canLoad
guard to prevent feature module from loading if the user is not authorized to access a route. You can usecanLoad
guard alongsidecanActivate
andcanActivateChild
guards which prevent unauthorized requests.
Preloading Strategy for Lazy-Loaded Modules
A preload strategy creates rules that determine which modules to preload. So, if you have multiple lazy-loaded modules, a preloading strategy would determine which modules to preload and when to preload them.
Angular supplies two preloading strategies out of the box:
NoPreloading
- No preloading (default)PreloadAllModules
- Preload of all lazy-loaded modules.
No Preloading – Default preloading strategy
@NgModule({
imports: [
RouterModule.forRoot(routes, { preloadingStrategy: NoPreloading })
],
exports: [RouterModule]
})
export class AppRoutingModule {}
Preloading All Modules
@NgModule({
imports: [
RouterModule.forRoot(routes, { preloadingStrategy: PreloadAllModules })
],
exports: [RouterModule]
})
Creating a Custom Preload Strategy
The first thing we need to do is to determine the formula/strategy to use to determine which lazy-loaded modules to preload. For instance, we can add a preload flag to the routes you want to preload and then check for the flag when determining whether to preload the lazy-loaded module:
{
path: 'module-8',
loadChildren: () => import('./lazymodule8/lazymodule8.module').then(m => m.Lazymodule8Module),
data: { preload: true } // preload flag
}
And then we are going to create a service that implements PreloadingStrategy
interface. To implement the interface, we are going to add a preload
function. The preload function accepts two arguments – a route and a loader function:
The route is the route to consider for preloading.
And the loader function loads the lazy-loaded module asynchronously when called.
Inside the preload function, we are going to check If the preload flag is set to true, and then return the loader function else we return a null observable.
export class MyPreloadingStrategyService implements PreloadingStrategy {
preload(route: Route, load: () => Observable<any>): Observable<any> {
if (route.data && route.data['preload']) {
return load();
} else {
return of(null);
}
}
}
And finally, we need to set the preload service we created above as the preloading strategy.
@NgModule({
imports: [
RouterModule.forRoot(routes, {
preloadingStrategy: MyPreloadingStrategyService // our preloading service here
})
],
exports: [RouterModule]
})
export class AppRoutingModule {}
Preload Strategy Demo
The following demo uses the preload strategy above. It has 8 routes, where only even-numbered routes are preloaded. After initially loading the application, the app is taken to offline mode and you will notice only preloaded routes load while the others fail due to lack of network.