Angular : Modules and lazy loading to improve loading time.

Are you a serious angular developer and ever felt that your angular app takes too much time to load initially? Then you should probably know about modules and lazy loading in angular. Here I am about to tell you why and how I implemented lazy loading in my angular app in 3 simple steps and reduced the loading time to 3 seconds from a worrying 20 seconds.

Here, I am going to assume that

  • You have a basic knowledge of angular 2+
  • You have a basic knowledge of routing in an angular app

The problem I faced

Recently I came across a problem in one of the angular projects I am working on that The initial loading of the application takes too much time: more than 20 seconds! The problem was very simple. The application bundle was too big for a fast loading – 4 MB. Yes, that is a very big bundle size for a JavaScript application(Since the browser has to do a lot of work to parse and analyse the script before actually running it). It was accountable since we had a lot of components and we used some heavy libraries in the application.

But the solution was not that simple. I tried replacing the heavy libraries with their lightweight versions. I succeeded with some and reduced the application bundle size by 1 MB. But it was not enough. There were some libraries that could not be replaced. That’s when I decided to try lazy loading.

What is lazy loading?

Lazy loading is a technique in angular by which we can load application modules on demand. The idea is simple; split the whole application into modules of smaller size and load them on demand. This will reduce the initial loadtime latency since the browser loads only the modules needed, not the entire application.

Let’s get started..

Here I am trying to explain the angular lazy loading in 3 simple steps. We will create/edit only 4 files by hand. The 3 simple steps are as follows

  1. Create an angular application
  2. Create a module
  3. Do the lazy loading

Step 1: Create an angular application

You all are familiar with this step. Use the angular-cli to create a new project.

ng new lazy-loading-app --routing

The option –routing creates the routing module for you.

Step 2: Create a module

Now lets create a module to be lazy loaded in step 3.

This will create a module with a component inside it, and setup the routing for it.

Goto the application directory(were 'lazy-loading-app') and execute the command

ng g module lazy-module --flat

You may or may not use the –flat option for a flat directory structure. If used, it will create the file lazy-module.module.ts in the directory lazy-loading-app/src/app. If not used, then it will create a directory lazy-module inside lazy-loading-app/src/app and the file lazy-module.module.ts will be created under the directory.

Module creation with –flat option
Module creation without –flat option
Note that we created just an ordinary module. No confusing configurations!!

Now, create a component inside the new module to be displayed in the final step. Plain old angular component creation 😉 With an exception to use –module option to specify the module to which the component belongs to. The option will make the necessary changes to the file lazy-module.module.ts to accommodate the new component. Open the files and see for yourself.

Create a component inside lazy module

We need one more thing to complete this module. Configure a router module! This is not a hard thing. If you already know about the routing module, create a similar .ts file inside the module directory and import it inside the module. The difference is that we don’t use the forRoot() function of RouterModule to initialize the routes. Instead, use forChild() function.

If you are new to router module, read this before proceeding.

We will create a file lazy-module.router.ts file inside lazy-loading-app/src/app/lazy-module.module.ts as follows

import { NgModule } from '@angular/core';
import { LazyComponentComponent } from './lazy-component/lazy-component.component';
import { Routes ,RouterModule} from '@angular/router';

const routes :Routes =
[
  {
    path:'laz-comp', component:LazyComponentComponent
  }
]

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

Note the path ‘laz-comp’. You will see it again later.

Now, import the router to the lazy module. The lazy-module.module.ts file will look as follows.

import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';
import { LazyComponentComponent } from './lazy-component/lazy-component.component';
import { LazyModuleRouter } from './lazy-module.router';

@NgModule({
  declarations: [LazyComponentComponent],
  imports: [
  	CommonModule,
  	LazyModuleRouter
  ]
})
export class LazyModuleModule { }

So that’s it. We created our lazy module with a component inside it, and have setup the routing for it.

Step 3: Do the lazy loading

For the lazy loading part, edit the app-routing.module.ts, the router for our main application and add a rout for our lazy component inside it. app-routing.module.ts is there in the directory lazy-loading-app/src/app. Open it and paste the following code.

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

const routes: Routes = [
	{
		path: 'lazy', loadChildren: './lazy-module/lazy-module.module#LazyModuleModule'
	}
];

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

Things to note here

1. For main application we use the forRoot() function of the RouterModule to initialize it. We used the forChild() function in the lazy module.

2. The most important part! Note how we have specified the lazy module to the router. We didn’t declare or import it. We just provided the path to the module as a string as the loadChildren field of the route. Since it is not imported, it will not be added to the JS bundle of the main application while compilation.

3. The loadChildren field: This is the way to tell the app router to lazy load the children of the module specified to that route(here ‘lazy’). Our lazy module has only one child; the ‘laz-comp’ path specified for LazyComponentComponent. This creates a router link to LazyComponentComponent : ‘/lazy/laz-comp’. If we had another rout specified in the router of the lazy module, say ‘another-rout’ for a component AnotherRoutComponent, loadChildren would have created another router link ‘/lazy/another-rout’ and so on.

Build the application and you will see the lazy module has been created as a JS chunk apart from the main.js chunk.

Congratulations!! We have created a lazy loading module. To see it in action, I have modified lazy-loading-app/src/app/app.component.html and added an anchor tag with router link to our lazy loaded component. See the screenshots below for lazy loading in action.

App initial loading

See, there is a link to open our lazy component at the bottom of the page.

After clicking on the link, the page will look like this..

Application after clicking on the link to load lazy component.
  1. Our lazy component is displayed in the screen
  2. The lazy module loaded when we clicked the link.

Lets conclude

Module splits the application into chunks of small sizes. Lazy loading loads only the chunks needed to operate as and when needed. Combine these two, your app will load fast.

The source code is available here

Leave a comment