Lazy Loading in Angular

With lazy loaded modules in Angular, it’s easy to have features loaded only when the user navigates to their routes for the first time. This can be a huge help for your app’s performance and reducing the initial bundle size. Plus, it’s pretty straightforward to setup!

The following covers lazy loading modules in Angular 2+ apps.

Feature Module

Lazy loaded routes need to be outside of the root app module, so you’ll want to have your lazy loaded features into feature modules.

Assuming that you have an Angular CLI project, let’s create a new feature module:

$ ng g module shop

Now let’s also create 3 components inside our shop feature module:

$ ng g c shop/cart
$ ng g c shop/checkout
$ ng g c shop/confirm

Don't import feature modules that should be lazy loaded in your app module, otherwise they'll be eager loaded.

loadChildren in Main Route Configuration

In your main routing configuration, you’ll want to do something like the following:

routes.ts

import { Routes } from '@angular/router';

// BoutiqueComponent is a normal, eager loaded component
import { BoutiqueComponent } from './boutique/boutique.component';

export const routes: Routes = [
  { path: '', component: BoutiqueComponent, pathMatch: 'full' },
  { path: 'shop', loadChildren: './shop/shop.module#ShopModule' },
  { path: '**', component: BoutiqueComponent }
];

Notice the odd-looking syntax with loadChildren: first, the path to the module, then #, followed by the module’s class name. This instructs the router that the module should be lazy loaded and tells it where to find the module.

Route Config in Feature Module

Now all that’s left to do is to configure routes specific to the feature module. Here’s an example:

shop/shop.routing.ts

import { Routes } from '@angular/router';

import { CartComponent } from './cart/cart.component';
import { CheckoutComponent } from './checkout/checkout.component';
import { ConfirmComponent } from './confirm/confirm.component';

export const routes: Routes = [
    { path: '', component: CartComponent },
    { path: 'checkout', component: CheckoutComponent },
    { path: 'confirm', component: ConfirmComponent },
];

And finally, in the feature module itself, you’ll include your routes with RouterModule’s forChild method instead of forRoot:

shop/shop.module.ts

import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';

import { CartComponent } from './cart/cart.component';
import { CheckoutComponent } from './checkout/checkout.component';
import { ConfirmComponent } from './confirm/confirm.component';

import { routes } from './shop.routing';
import { RouterModule } from '@angular/router';


@NgModule({
  imports: [
    RouterModule.forChild(routes)
  ],
  declarations: [CartComponent, CheckoutComponent, ConfirmComponent]
})
export class LegalModule { }

😋 And that’s all there is to it! No you can use the routerLink directive to navigate to /shop, /shop/checkout or /shop/confirm and the module will be loaded the first time one of these paths are navigated to.

Tip: If it's not working right away, try restarting your server.


Verify that lazy loading works in DevTools by seeing if a new chunk is loaded when navigating to a route on the lazy loaded module:

Lazy loading module in the Devtool network tab

✖ Clear

🕵 Search Results

🔎 Searching...