DEV Community

Madhu Sudhanan P
Madhu Sudhanan P

Posted on

Conditionally lazy load modules in Angular

Image description

The lazy loading module is an important feature that helps to improve the performance of an Angular application. This feature is amazing and resolves most of the use cases.
Recently, I faced a user scenario where I need to load a module for a route path conditionally. The scenario is that if a user is assigned with some permission, then load a module or load another module.
The use case seems legit, but I was unable to achieve this using the current lazy loading module feature.
In the current lazy loading feature, we will use loadChildren property to load the required module. The caveat here is that loadChildren doesn’t provide any argument or injectable services which limit us from conditionally loading modules.

const routes: Routes = [{
       path:'view',
       loadChildren: () => import('./modules/view/view.module')
                                .then(x => x.ViewModule)
}];
@NgModule({
   imports: [RouterModule.forRoot(routes, { useHash: true })],
   exports: [RouterModule]
})
export class AppRoutingModule { }
Enter fullscreen mode Exit fullscreen mode

To tackle this, I am using the router events to change the loadChildren method definition. We can listen for the RouteConfigLoadStart event which will be triggered before loading the lazy modules.
Since we are configuring the loadChildren method inside the router event handler, we are now provided with injectable services & other options which will provide more control over the module loading.

import { Component } from '@angular/core';
import { RouteConfigLoadStart, Router } from '@angular/router';
@Component({
 selector: 'my-app',
 templateUrl: './app.component.html',
  styleUrls: ['./app.component.css'],
})
export class AppComponent {
  name = 'Conditionally lazy load modules';
  enableEdit = false;
 constructor(private router: Router) {
  this.router.events.subscribe((x) => {
    console.log(x);
    if (x instanceof RouteConfigLoadStart && x.route.path === 'viewedit') {
        x.route.loadChildren = () => {
          if (!this.enableEdit) {
            return import('./modules/view/view.module').then((mod) => mod.ViewModule);
   } else {
       return import('./modules/edit/edit.module').then((mod) => mod.EditModule);
    }
   };
  }
 });
}
. . . 
}
Enter fullscreen mode Exit fullscreen mode

The complete working sample can be found in the below StackBlitz.

Feel free to contact me. Happy coding!!

Top comments (0)