Lazy Loading In Angular

Lazy Loading In Angular

In this article, we will learn how to use lazy loading. The term "lazy loading" refers to a process in which angular loads Modules just when needed rather than all at once. On-demand loading is another term for it. By default, Angular eagerly loads the modules. The initial load time of the app is reduced by using lazy loading of Angular Modules. When the user navigates to a route, we use the Angular Router's loadChilden function to lazy load them.

Why Lazy load?

As we add more functionality to our Angular apps, they grow in size. Angular Modules assist us in managing our app by allowing us to create different modules for each new feature. However, as the application grows in size, it takes longer to load. Because angular loads the complete application upfront, this is the case.

The user does not have a positive impression of the app because it takes so long to load. The app appears to run faster to the user when only a portion of the app is loaded (i.e. lazy loading). The faster loading software improves performance while also providing a positive user experience.

How Lazy loading works

Lazy loading in Angular is done at the module level. That is, only the Angular Modules can be lazy-loaded. Individual components cannot be loaded in a slow manner.

The Angular Router Module is used to implement lazy loading. The Angular Router's loadChildren function is in charge of loading the Modules.

When we define the routes, we specify the modules we want to load slowly.

We have a new syntax for lazy loading starting with Angular 8.

{path: "admin", loadChildren: () => import('./admin/admin.module').then(m => m.AdminModule)},

The admin is the path in the AdminModule's URL path section. We configure the Lazy Loading in the loadChildren section.

loadChildren

To the loadChildren argument, we must give a callback method. The AdminModule must be loaded in the callback. Using the import approach, we employ the dynamic import syntax. The import method loads the module from the path passed to it as an argument.

import('./admin/admin.module').then(m => m.AdminModule)

The router will download the AdminModule and load the routes and components of the AdminModule when the user navigates to the admin URL or any of its child routes, such as admin/dashboard.

The lazy loaded module is only loaded on the initial visit to the URL; it is not loaded again when we return to that URL.

Angular creates a separate bundle for the entire module when we define an AdminModule to be lazy-loaded.

Angular Lazy Loading Example

Let's make a basic app. There will be two components in the app. The first is SharedModule, which we eagerly load. AdminModule is the other module. We load the AdminModule eagerly at first, then update it to use Lazy Loading afterward.

Admin Module

DashboardComponent, RightsComponent, and UserComponent are the three components of the AdminModule. Three routes are specified as children of the Admin Route defined in the AdminRoutingModule in the Module.

{  path: 'admin',
	children :[
		{ path: 'dashboard', component: DashboardComponent},
		{ path: 'user', component: UserComponent},
		{ path: 'rights', component: RightsComponent},
	]
},

The forChild() function is used to register the routes listed above

AdminModule's whole source code may be found below.

Add the following code under the src/app/admin/pages/dashboard/dashboard.component.ts:

import { Component } from '@angular/core';

@Component({
  template: `<h1>Dashboard Component</h1>`,
})
export class DashboardComponent {
  title = '';
}

Add the following code under the src/app/admin/pages/rights/rights.component.ts:

import { Component } from '@angular/core';
 
@Component({
  template: '<h1>Rights Component</h1>',
})
export class RightsComponent {
  title = '';
}

Add the following code under the src/app/admin/pages/user/user.component.ts:

import { Component } from '@angular/core';
 
@Component({
  template: '<h1>User Component</h1>',
})
export class UserComponent {
  title = '';
}

Add the following code under the src/app/admin/pages/index.ts:

export * from './dashboard/dashboard.component';
export * from './rights/rights.component';
export * from './user/user.component';

Add the following code under the src/app/admin/admin.routing.module.ts:

import { NgModule } from '@angular/core';
import { Routes, RouterModule } from '@angular/router';
 
import { UserComponent , RightsComponent ,DashboardComponent } from './pages';
 
const routes: Routes = [
    {  path: 'admin',
        children :[
            { path: 'dashboard', component: DashboardComponent},
            { path: 'user', component: UserComponent},
            { path: 'rights', component: RightsComponent},
        ]
    },
];
 
@NgModule({
  imports: [RouterModule.forChild(routes)],
  exports: [RouterModule]
})
export class AdminRoutingModule { }

Add the following code under the src/app/admin/admin.module.ts:

import { NgModule } from '@angular/core';
 
import { AdminRoutingModule } from './admin.routing.module';
import { UserComponent,RightsComponent,DashboardComponent } from './pages';
 
 
@NgModule({
  declarations: [UserComponent,RightsComponent,DashboardComponent],
  imports: [
    AdminRoutingModule,
  ],
  providers: [],
})
export class AdminModule { }

export * from './admin.module';
export * from './pages';

Shared Module

HeaderComponent and FooterComponent are included in the SharedModule. The navigation menu is contained in the HeaderComponent.

Add the following code under the src/app/shared/layout/footer/footer.component.ts:

import { Component } from '@angular/core';
 
@Component({
  selector: 'app-footer',
  templateUrl: './footer.component.html'
})
export class FooterComponent {
}

Add the following code under the src/app/shared/layout/footer/footer.component.html:

<p>(c) All Rights Reserved</p>

Add the following code under the src/app/shared/layout/header/header.component.ts:

import { Component, OnInit } from '@angular/core';
 
@Component({
  selector: 'app-header',
  templateUrl: './header.component.html',
  styleUrls: ['./header.component.css']
})
export class HeaderComponent {
}

Add the following code under the src/app/shared/layout/footer/footer.component.ts:

<ul>
    <li>
      <a class="navbar-brand" routerlink="">home</a>
    </li>
    <li>
      <a class="navbar-brand" routerlink="/admin/dashboard">Dashboard</a>
    </li>
    <li>
      <a class="navbar-brand" routerlink="/admin/rights">rights</a>
  </li>
  <li>
    <a class="navbar-brand" routerlink="/admin/user">user</a>
  </li>
</ul>

Add the following code under the src/app/shared/layout/header/header.component.css:

ul {
    list-style-type: none;
    margin: 0;
    padding: 0;
    overflow: hidden;
    background-color: #333333;
}
 
li {
    float: left;
}
 
li a {
    display: block;
    color: white;
    text-align: center;
    padding: 16px;
    text-decoration: none;
}
 
li a:hover {
    background-color: #111111;
}

Add the following code under the src/app/shared/layout/index.ts:

export * from './footer/footer.component';
export * from './header/header.component';

Add the following code under the src/app/shared/shared.module.ts
import { CommonModule } from '@angular/common';
import { NgModule } from '@angular/core';
import { FormsModule, ReactiveFormsModule } from '@angular/forms';
import { HttpClientModule } from '@angular/common/http';
import { RouterModule } from '@angular/router';
import { HeaderComponent, FooterComponent } from './layout';
 
 
@NgModule({
  imports: [
    CommonModule,
    FormsModule,
    ReactiveFormsModule,
    HttpClientModule,
    RouterModule
  ],
  declarations: [ HeaderComponent,FooterComponent ],
  exports: [
    CommonModule,
    FormsModule,
    ReactiveFormsModule,
    HttpClientModule,
    RouterModule,
    HeaderComponent,FooterComponent
  ]
})
export class SharedModule {
}

Add the following code under the src/app/shared/index.ts:

export * from './shared.module';
export * from './layout';

Root Module

The forRoot function is used by the Root Module to register the routes. There are currently no routes available. The AdminModule is also imported.

import { Component } from '@angular/core';
import { HeaderComponent, FooterComponent } from './shared';
 
@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})
export class AppComponent {
  title = 'Module Demo';
}

Add the following code under the app.component.html:

<app-header></app-header>
 
<h1>Lazy loaded module Demo</h1>
 
<router-outlet></router-outlet>
<app-footer></app-footer>

Add the following code under the app.routing.module.html:

import { NgModule } from '@angular/core';
import { Routes, RouterModule } from '@angular/router';
 
const routes: Routes = [
];
 
@NgModule({
  imports: [RouterModule.forRoot(routes)],
  exports: [RouterModule]
})
export class AppRoutingModule { }

Add the following code under the app.module.html:

import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
 
import { AppRoutingModule } from './app-routing.module';
 
import { AppComponent } from './app.component';
import { SharedModule} from './shared';
import { AdminModule} from './admin';
 
@NgModule({
  declarations: [
    AppComponent, 
  ],
  imports: [
    BrowserModule,
    AppRoutingModule,
    SharedModule,
    AdminModule
  ],
  providers: [],
  bootstrap: [AppComponent]
})
export class AppModule { }

Run the app to see how it works.

The five JavaScript files (called chunks) generated by the ng Serve command are main.js, polyfills.js, runtime.js, styles.js, and vendor.js. These are added to the main.js file as you add more features.


Example of Lazy Loading In Angular


To access the chrome developer console and the network tab, press Ctrl + Shift + I. When you run the app, you'll notice that all of the pieces are loaded up front.

Example of Lazy Loading In Angular



Lazy loading the AdminModule

First, we must add the following route to the AppRoutingModule in order to Lazy Load AdminModule. When the user navigates to the Admin route, this route informs the router to load the AdminModule from the path ./admin/admin/module.ts.

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

The import of AdminModule from the AppModule must then be removed. If you don't, the module will be eagerly loaded.

Finally, we must update the AdminRoutingModule's route specification. The parent route admin has been removed because it has been transferred to the AppRoutingModule. Because this is a lazy-loaded module, the routes we define will become the admin's child route.

const routes: Routes = [
    { path: 'dashboard', component: DashboardComponent},
    { path: 'user', component: UserComponent},
    { path: 'rights', component: RightsComponent},
];

The admin-admin.module.js file will now be visible when you perform the ng serve command. Each lazy loaded module is given its own js file by the Angular compiler. This file is only loaded when the router requires it.

Example of Lazy Loading In Angular


You may put it to the test by starting the application. When you launch the app, you'll notice that admin-admin.module.js isn't loaded. Only when you click on the Dashboard, User, or Rights menus does it load.

Example of Lazy Loading In Angular



Services in Lazy Loaded Module

When creating or providing services in the Lazy loaded module, we must exercise caution.

Any service described in the Lazy Loaded Module will not be loaded until the user clicks on it. As a result, we can't use them anyplace else in the application.

For the lazy loaded module, Angular produces a second injector. As a result, each service we give in the lazy loaded module has its own instance.

As a result, only construct a service in the lazy loaded module if it will be used within that module. Otherwise, consider putting it in an AppModule or a separate CoreModule. For further information, see Angular's Folder Structure.

Dos and Don't of Lazy loaded Modules

Importing lazy loaded modules into other modules is not recommended. This will cause Angular to eagerly load the module, which may result in unexpected issues.

When importing other modules into the lazy-loaded module, be cautious. If any services are provided by other modules, the lazy loaded module will receive a new instance of the service. If the services are intended to be app-wide singletons, this could have unforeseen consequences.

Conclusion

One of the best features of Angular is the Angular Modules and their slow loading. The SharedModule and CoreModule should be loaded first, and the remainder of the application should be loaded later.

I hope this article helps you and you will like it.👍

If you have any doubt or confusion then free to ask in the comment section.

Post a Comment

Previous Post Next Post