Angular is a frontend JavaScript framework developed by Google for building scalable enterprise-grade web applications. Some of these applications can get quite large, affecting the load time of your application.
To reduce load time and improve the overall experience of your users, you can use a technique known as lazy loading. This native Angular feature allows you to load only the required bits of the web app first, then load other modules as needed.
In this article, you will learn about lazy loading and how it can help speed up your web app.
What is Lazy Loading?
Lazy loading refers to the technique of loading webpage elements only when they are required. Its counterpart is eager loading, when everything loads — or tries to load — immediately. Fetching all images, videos, CSS, and JavaScript code eagerly might mean long load times — bad news for users.
Lazy loading is often used for images and videos on sites that host a lot of content. Instead of loading all media at once, which would use a lot of bandwidth and bog down page views, those elements are loaded when their location on the page is about to scroll into view.
Angular is a single-page application framework that relies on JavaScript for much of its functionality. Your app’s collection of JavaScript can easily become large as the app grows, and this comes with a corresponding increase in data use and load time. To speed things up, you can use lazy loading to first fetch required modules and defer the loading of other modules until they are needed.
Benefits of Lazy Loading in Angular
Lazy loading offers benefits that will make your site more user-friendly. These include:
- Faster load time: JavaScript contains instructions for displaying your page and loading its data. Because of this, it’s a render-blocking resource. This means the browser has to wait to load all of the JavaScript before rendering your page. When lazy loading in Angular, the JavaScript is split into chunks that are loaded separately. The initial chunk contains only logic that is needed for the main module of the page. It is loaded eagerly, then the remaining modules are loaded lazily. By reducing the size of the initial chunk, you’ll make the site load and render faster.
- Less data usage: By splitting the data into chunks and loading as needed, you might use less bandwidth.
- Conserved browser resources: Since the browser loads only the chunks that are needed, it doesn’t waste memory and CPU trying to interpret and render code that isn’t required.
Implementing Lazy Loading in Angular
To follow along with this tutorial, you will need the following:
- NodeJS installed
- Basic knowledge of Angular
Step Up Your Project
You’ll use the Angular CLI to create your project. You can install the CLI using npm by running the command:
npm install -g @angular/cli
After that, create a project named Lazy Loading Demo like this:
ng new lazy-loading-demo --routing
That command creates a new Angular project, complete with routing. You’ll be working exclusively in the src/app
folder, which contains the code for your app. This folder contains your main routing file, app-routing.module.ts
. The structure of the folder should look like this:
Create a Feature Module with Routes
Next, you’ll create a feature module that will load lazily. To create this module, run this command:
ng generate module blog --route blog --module app.module
This command creates a module named BlogModule
, along with routing. If you open src
/app/app-routing.module.ts
, you will see it now looks like this:
import { NgModule } from '@angular/core';
import { RouterModule, Routes } from '@angular/router';
const routes: Routes = [ { path: 'blog', loadChildren: () => import('./blog/blog.module').then(m => m.BlogModule) }];
@NgModule({
imports: [RouterModule.forRoot(routes)],
exports: [RouterModule]
})
export class AppRoutingModule { }
The part that is important for lazy loading is the third line:
const routes: Routes = [ { path: 'blog', loadChildren: () => import('./blog/blog.module').then(m => m.BlogModule) }];
That line defines the routes. The route for the blog uses the loadChildren
argument instead of component
. The loadChildren
argument tells Angular to lazy load the route — to dynamically import the module only when the route is visited, and then return it to the router. The module defines its own child routes, such as blog/**
, in its routing.module.ts
file. The blog module you generated looks like this:
import { NgModule } from '@angular/core';
import { RouterModule, Routes } from '@angular/router';
import { BlogComponent } from './blog.component';
const routes: Routes = [{ path: '', component: BlogComponent }];
@NgModule({
imports: [RouterModule.forChild(routes)],
exports: [RouterModule]
})
export class BlogRoutingModule { }
You will note that this routing file contains a single route, ''
. This resolves for /blog
and points to the BlogComponent. You can add more components and define those routes in this file.
For example, if you wanted to add a component that would pull details about a particular blog post, you could create the component with this command:
ng generate component blog/detail
That generates the component for the blog detail and adds it to the blog module. To add a route for it, you can simply add it to your routes array:
const routes: Routes = [{ path: '', component: BlogComponent },
{path:"/:title",component: DetailComponent}];
This adds a route that resolves for blog/:title
(for example, blog/angular-tutorial
). This array of routes is lazy-loaded and not included in the initial bundle.
Verify Lazy Loading
You can easily check that lazy loading is working by running ng serve
and observing the output. At the bottom of your output, you should get something like this:
The output above is divided into two parts: Initial Chunk Files
are the files loaded when the page first loads. Lazy Chunk Files
are lazy-loaded. The blog module is listed in this example.
Checking for Lazy Loading Through Browser Network Logs
Another way to confirm lazy loading is by using the Network tab in your browser’s Developer Tools panel. (On Windows, that’s F12 in Chrome and Microsoft Edge, and Ctrl–Shift–I in Firefox. On a Mac, that’s Command–Option–I in Chrome, Firefox and Safari.)
Select the JS
filter to view only JavaScript files loaded over the network. After the initial load of the app, you should get something like this:
When you navigate to /blog
, you will notice a new chunk, src_app_blog_blog_module_ts.js
, is loaded. This means your module was requested only when you navigated to that route, and it is being lazily loaded. The network log should look something like this:
Lazy Loading vs Eager Loading
For comparison, let’s also create an eagerly loaded module and see how it impacts the file size and load time. To demonstrate this, you’ll create a module for authentication. Such a module might need to be loaded eagerly, as authentication is something you might require all users to do.
Generate an AuthModule by running this command in the CLI:
ng generate module auth --routing --module app.module
That generates the module and a routing file. It also adds the module to the app.module.ts
file. However, unlike the command we used to generate a module last time, this one doesn’t add a lazy-loaded route. It uses the --routing
parameter instead of --route <name>
. That adds the authentication module to the imports
array in app.module.ts
:
@NgModule({
declarations: [
AppComponent
],
imports: [
BrowserModule,
AppRoutingModule,
AuthModule //added auth module
],
providers: [],
bootstrap: [AppComponent]
})
Adding AuthModule to your AppModule imports array means the authentication module is added to the initial chunk files and will be included with the main JavaScript bundle. To verify this, you can run ng serve
again and observe the output:
As you can see, the authentication module is not included as part of the lazy chunk files. Additionally, the size of the initial bundle has increased. The main.js
file almost doubled in size, increasing from 8 KB to 15 KB. In this example, the increase is small, since the components don’t contain much code. But, as you fill the components with logic, this file size will increase, making a strong case for lazy loading.
Summary
You’ve learned how to use lazy loading in Angular to fetch modules only when they are required. Lazy loading is a great technique to improve load times, reduce data usage, and better utilize your frontend and backend resources.
Lazy loading, along with technology like content distribution networks and minifying JavaScript, will improve both your website’s performance and your users’ satisfaction.
If you’re developing a WordPress site and want to really crank up the speed, read about Kinsta Edge Caching to see some impressive numbers.
Leave a Reply