Learnitweb

Lazy-loading feature modules in Angular

1. Introduction

By default, Angular modules are eagerly loaded. This means that all NgModules are loaded as soon as the application loads. All NgModules are loaded whether they are required or not. This increases the load time of the page. This is not a good design. Suppose there are certain modules in your application which are rarely used, then it will be a good design to load these modules only when they are needed.

Lazy loading of modules helps in keeping the bundle size less and improve page load time.

2. What you’ll do in this tutorial?

You’ll do the following in this tutorial:

  1. Create a new application with routing enabled.
  2. Create two modules.
  3. Enable lazy loading of modules.
  4. Verify the lazy loading of modules.

You’ll understand the changes required to enable lazy loading of feature modules in application.

3. How to enable lazy loading in application?

3.1 Remove lazy-loaded module from the imports array of AppModule.

3.2 To lazy load a module in Angular, use loadChildren instead of Component in AppRoutingModule routes configuration.

const routes: Routes = [
  {
    path: 'admin',
    loadChildren: () =>
      import('./admin/admin.module').then((m) => m.AdminModule),
  },
  {
    path: 'user',
    loadChildren: () => import('./user/user.module').then((m) => m.UserModule),
  },
];

3.3 The route for the component is to be added in the lazy-loaded module’s routing module.

const routes: Routes = [{ path: '', component: AdminComponent }];

4. Step-by-step implementation of lazy loading

Step 1: Create an application

We’ll create a new application to demonstrate lazy-loading of modules. If you already have an application, you can use that one too. The application should have routing enabled.

ng new lazy-loading-example --routing

This will create a new application lazy-loading-example. The application will have AppRoutingModule to have route configuration.

Step 2: Create feature modules

We’ll create two feature modules – admin and user, to demonstrate lazy-loading of modules in our application. Run the following commands to generate the modules:

ng generate module admin --route admin --module app.module
ng generate module user --route user --module app.module
  • admin and user are the name of modules in the command.
  • Routing is enabled for these modules and each module will have its own routing module – AdminRoutingModule and UserRoutingModule.
  • Commands generate AdminComponent and UserComponent in admin and user folders respectively.
  • Lazy loading configuration is automatically generated in AppRoutingModule.
const routes: Routes = [
  {
    path: 'admin',
    loadChildren: () =>
      import('./admin/admin.module').then((m) => m.AdminModule),
  },
  {
    path: 'user',
    loadChildren: () => import('./user/user.module').then((m) => m.UserModule),
  },
];
  • Route configuration of AdminComponent is automatically added to AdminRoutingModule.
const routes: Routes = [{ path: '', component: AdminComponent }];
  • Route configuration of UserComponent is automatically added to UserRoutingModule
const routes: Routes = [{ path: '', component: UserComponent }];

Step 3: Change UI to test lazy loading

Change app.component.html file to the following:

<h1>
  {{ title }}
</h1>

<button routerLink="/admin">Admin</button>
<button routerLink="/user">User</button>
<button routerLink="">Home</button>

<router-outlet></router-outlet>

This will add three buttons, Customers, Orders and Home. The objective is to load the AdminModule when Admin button is clicked, load UserModule when User button is clicked and Home is the default page.

Step 4: Add route configuration for Home button in AdminRoutingModule

 {
    path: '',
    redirectTo: '',
    pathMatch: 'full',
  },

Following is the complete code of files we discussed.

src/app/admin/admin-routing.module.ts

import { NgModule } from '@angular/core';
import { RouterModule, Routes } from '@angular/router';
import { AdminComponent } from './admin.component';

const routes: Routes = [{ path: '', component: AdminComponent }];

@NgModule({
  imports: [RouterModule.forChild(routes)],
  exports: [RouterModule],
})
export class AdminRoutingModule {}

src/app/admin/admin.module.ts

import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';

import { AdminRoutingModule } from './admin-routing.module';
import { AdminComponent } from './admin.component';


@NgModule({
  declarations: [
    AdminComponent
  ],
  imports: [
    CommonModule,
    AdminRoutingModule
  ]
})
export class AdminModule { }

src/app/admin/user-routing.module.ts

import { NgModule } from '@angular/core';
import { RouterModule, Routes } from '@angular/router';
import { UserComponent } from './user.component';

const routes: Routes = [{ path: '', component: UserComponent }];

@NgModule({
  imports: [RouterModule.forChild(routes)],
  exports: [RouterModule]
})
export class UserRoutingModule { }

src/app/admin/user.module.ts

import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';

import { UserRoutingModule } from './user-routing.module';
import { UserComponent } from './user.component';


@NgModule({
  declarations: [
    UserComponent
  ],
  imports: [
    CommonModule,
    UserRoutingModule
  ]
})
export class UserModule { }

src/app/app-routing.module.ts

import { NgModule } from '@angular/core';
import { RouterModule, Routes } from '@angular/router';

const routes: Routes = [
  {
    path: 'admin',
    loadChildren: () =>
      import('./admin/admin.module').then((m) => m.AdminModule),
  },
  {
    path: 'user',
    loadChildren: () => import('./user/user.module').then((m) => m.UserModule),
  },
  {
    path: '',
    redirectTo: '',
    pathMatch: 'full',
  },
];

@NgModule({
  imports: [RouterModule.forRoot(routes)],
  exports: [RouterModule],
})
export class AppRoutingModule {}

src/app/app.component.html

<h1>
  {{ title }}
</h1>

<button routerLink="/admin">Admin</button>
<button routerLink="/user">User</button>
<button routerLink="">Home</button>

<router-outlet></router-outlet>

src/app/app.module.ts

import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';

import { AppRoutingModule } from './app-routing.module';
import { AppComponent } from './app.component';

@NgModule({
  declarations: [
    AppComponent
  ],
  imports: [
    BrowserModule,
    AppRoutingModule
  ],
  providers: [],
  bootstrap: [AppComponent]
})
export class AppModule { }

Step 5: Verify the lazy loading of modules.

  • Run the application using ng serve command. The output should like this:
lazy loading ngmodule example
  • Open the browser “Network” tab as shown and click on the “Admin” button.
lazy loading NgModule verification

Observe the loading of file src_app_admin_admin_module_ts.js.

Now clear the list and click on “User” button and observe the src_app_user_user_module_ts.js is loaded. If the output is same as mentioned then your lazy-loading configuration is working fine.

5. Conclusion

In this tutorial, we discussed lazy loading of NgModules. We also discussed the benefits and step-by-step implementation. We hope this tutorial was informative. Happy learning!