Lazy Loading in Angular — A Quick Guide

Alexander Obregon
5 min readJul 15, 2023

--

Image Source

Introduction

Angular has been lauded for its ability to make the development process more manageable, thanks to its range of features. One such feature, which is an essential tool in enhancing app performance, is lazy loading. In this guide, we’ll delve deep into the world of Angular’s lazy loading, detailing its advantages, implementation, and some tips to get the best out of it.

Understanding Lazy Loading

Lazy loading is a design pattern that defers the initialization of an object until it’s needed. This pattern can significantly enhance the performance of your Angular application by splitting it into multiple bundles, which are loaded on demand.

Why is this useful? Consider a large Angular application with numerous components, each of them corresponding to a different feature. Traditionally, when a user visits the app, they have to download the entire JavaScript bundle, which can be significantly large and slow down the app loading time. With lazy loading, the user only downloads what they need when they need it, thereby making the initial load of the application faster.

Implementing Lazy Loading in Angular

Now that we understand what lazy loading is and its importance let’s delve into how you can implement it in your Angular application.

Setting Up The Routes

To start with, we’ll need to setup routes. For the sake of this example, let’s assume you have an application with two main components: HomeComponent and AboutComponent.

Normally, your routing might look like this:

const routes: Routes = [
{ path: '', component: HomeComponent },
{ path: 'about', component: AboutComponent }
];

But with lazy loading, we’ll need to modify this by using the loadChildren property instead of component.

const routes: Routes = [
{ path: '', component: HomeComponent },
{ path: 'about', loadChildren: () => import('./about/about.module').then(m => m.AboutModule) }
];

In this case, AboutModule will only be loaded when the user navigates to the /about route.

Creating Feature Modules

Each lazily-loaded bundle corresponds to a feature module. In this example, AboutModule is our feature module. In order to define a feature module, you'll need to create a module and define the routes for the module.

Here’s how your AboutModule might look:

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

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

@NgModule({
imports: [RouterModule.forChild(routes)],
declarations: [AboutComponent]
})
export class AboutModule { }

Notice how we’re using RouterModule.forChild(routes) instead of RouterModule.forRoot(routes). This is because forRoot() should only be used in the AppModule, while forChild() is used in feature modules.

Preloading Strategy

Angular also provides two preloading strategies that determine how to preload these lazily-loaded modules: PreloadAllModules and NoPreloading.

The NoPreloading strategy, which is the default, doesn’t preload any of the lazy-loaded modules.

The PreloadAllModules strategy preloads all lazy-loaded modules, meaning they’re loaded as soon as all eagerly-loaded modules are ready.

You can also create your own custom preloading strategy if the existing strategies don’t meet your needs. Here’s how you can define your routing to use a particular strategy:

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

Tips for Effective Lazy Loading

While lazy loading can significantly enhance your application’s performance, it’s crucial to use it judiciously to avoid creating too many bundles. Too many bundles can lead to an excessive number of HTTP requests, which could negate the benefits of lazy loading.

Here are some tips for effective lazy loading:

  1. Split Wisely: Split your application based on features that make sense to be loaded independently. Each feature module should represent a distinct feature of your application.
  2. Analyze Your Bundles: Use bundle analysis tools such as Webpack Bundle Analyzer to identify modules that are larger than necessary.
  3. Avoid Duplicate Imports: When using shared modules, make sure they’re not imported in multiple modules, as this can cause them to be included in multiple bundles.
  4. Custom Preloading Strategy: Consider using a custom preloading strategy if the existing ones don’t suit your needs. For example, you could preload some modules based on user behavior or network conditions.

Verifying Lazy Loading

Once you’ve implemented lazy loading, it’s essential to verify that it’s working as expected. You can use the Network tab in your browser’s Developer Tools to observe the network requests made by your application.

When you load the application, you should see a request for the main bundle and other eagerly loaded bundles. As you navigate to a lazily loaded route, you should see a new request for the corresponding bundle.

Pitfalls to Avoid

As powerful as lazy loading is, there are potential pitfalls that could hinder its effectiveness or create other issues.

  1. Avoid Lazy Loading Everything: While it might be tempting to lazy load all the modules in your application, doing so could increase the number of HTTP requests, which could hurt performance.
  2. Watch Out for Complex Dependencies: Lazy loaded modules should be as independent as possible. If a lazy-loaded module depends on another lazy-loaded module, you might end up with complex dependencies that can cause issues.
  3. Don’t Forget Error Handling: Implementing error handling for cases where a module fails to load is critical. You don’t want your users to end up on a broken page because a module failed to load.

Impact on SEO

Lazy loading can impact Search Engine Optimization (SEO) positively and negatively. On the one hand, lazy loading can improve page speed, a significant factor in search engine rankings. However, if implemented improperly, search engines might not be able to crawl and index lazily loaded content.

To ensure that your content is crawlable, you might need to use dynamic rendering, a technique where you serve a pre-rendered, static version of your application to search engine bots. Angular Universal is a tool you can use to implement dynamic rendering in your Angular application.

Conclusion

Lazy loading is a compelling performance optimization technique for Angular applications, especially for large applications. By understanding how to implement it, verify it, and navigate the potential pitfalls, you can significantly improve your application’s performance without degrading the user experience. Also, keeping in mind the SEO implications will ensure that your application remains discoverable. Always remember, a well-implemented lazy-loading strategy makes for a swift, smooth, and SEO-friendly user experience.

  1. Angular Documentation — Lazy Loading
  2. Angular Documentation — Preloading Modules

--

--

Alexander Obregon

Software Engineer, fervent coder & writer. Devoted to learning & assisting others. Connect on LinkedIn: https://www.linkedin.com/in/alexander-obregon-97849b229/