TL; DR: Lazy loading in Angular improves app performance by loading modules only when needed. This reduces initial load time and improves user experience.
Angular is a globally used framework for building extremely complex and high-performing web applications at scale. However, as your app grows, performance issues might start to show if you haven’t designed your Angular app properly.
As a result, many developers use lazy loading when developing production-level Angular apps. This technique reduces the size of data transferred over the network by breaking the build bundle into smaller chunks and helps the app respond quickly. This article will guide you through implementing lazy loading for Angular and compare the loading times to show the performance gain.
Angular uses its routing system for lazy loading. When a user initially starts the app, it will only load the AppModule or any other starting module you have defined. Then, as the user navigates through the app, Angular will check the route and load the module related to that route on demand. Here are the benefits of this approach:
Let’s walk through the process of implementing lazy loading in an Angular app. We’ll create a simple project with multiple feature modules to demonstrate this concept.
npm install -g @angular/cli
ng version
Create a new Angular app using the following command:
ng new lazy-loading-demo --no-standalone --routing
In the wizard, you will get a prompt to select the preferred styling format. For this example, I have selected CSS.
cd lazy-loading-demo
Start the development server to ensure everything is set up correctly:
ng serve
Create a new Angular module and a component for lazy loading:
ng generate module image-gallery --route image-gallery --module app.module
Then, update the image-gallery.component.ts file with the following code.
import { Component } from '@angular/core'; @Component({ selector: 'app-image-gallery', templateUrl: './image-gallery.component.html', styleUrls: ['./image-gallery.component.css'] }) export class ImageGalleryComponent { imageUrls: string[] = []; ngOnInit(): void { this.loadImages(); } loadImages(): void { this.imageUrls = [ // Add Image Urls here ]; } }
Update the image-gallery-routing.module.ts file to set up the routing for the lazy-loaded module:
import { NgModule } from '@angular/core'; import { RouterModule, Routes } from '@angular/router'; import { ImageGalleryComponent } from './image-gallery.component'; const routes: Routes = [{ path: '', component: ImageGalleryComponent }]; @NgModule({ imports: [RouterModule.forChild(routes)], exports: [RouterModule] }) export class ImageGalleryRoutingModule { }
Update the image-gallery.module.ts file to include the component and routing module.
import { NgModule } from '@angular/core'; import { CommonModule } from '@angular/common'; import { ImageGalleryRoutingModule } from './image-gallery-routing.module'; import { ImageGalleryComponent } from './image-gallery.component'; @NgModule({ declarations: [ ImageGalleryComponent ], imports: [ CommonModule, ImageGalleryRoutingModule ] }) export class ImageGalleryModule { }
Now, update your app-routing.module.ts file to include the lazy-loaded route.
import { NgModule } from '@angular/core'; import { RouterModule, Routes } from '@angular/router'; const routes: Routes = [ { path: 'images', loadChildren: () => import('./image-gallery/image-gallery.module').then(m => m.ImageGalleryModule) }, ]; @NgModule({ imports: [RouterModule.forRoot(routes)], exports: [RouterModule] }) export class AppRoutingModule { }
Make sure the AppRoutingModule is imported into the main app.module.ts file.
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 { }
Now, update the app.component.html file with the following code to include navigation.
<div class="image-gallery"> <div class="image-item" *ngFor="let imageUrl of imageUrls"> <img [src]="imageUrl" alt="Image"> </div> </div>
Start the app using the ng serve command and navigate to http://localhost:4200 in your browser.
With lazy loading
Without lazy loading:
As you can see, there’s a clear difference between the bundle sizes with and without lazy loading.
You might not see a massive difference here since the app is small. But, as your app grows, these numbers will significantly impact its app performance.
While this basic implementation demonstrates lazy loading, there are further optimizations you can consider:
Remember, performance optimization is an iterative process. Regularly measure your app’s performance, implement optimizations, and re-measure to ensure continuous improvement.
When using lazy loading in Angular, developers might face some common problems. Here are some of the most common issues and how to fix them:
Module not found errors are generally caused by a wrong path for a lazy-loaded module or a missing module file.
Circular dependencies may affect lazy loading and the performance of an app as a whole.
Incorrect routing configurations can prevent lazy-loaded modules from functioning.
If you wish to check out the full code, explore my GitHub repository.
Lazy loading delays loading parts of the app until they are required. This reduces network data transfer since you don’t have to load everything at once, which ultimately speeds up the loading process.
If you are planning to start a new project, I highly recommend you follow this guide and design it based on lazy loading from scratch. If you already have an existing project, you can start by finding parts in your current projects that could use lazy loading and slowly implementing this method.
Thank you for reading!