Lazy Loading Routes 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 8+ 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.

🐊 Alligator.io recommends

Our recommended Angular courses

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: () => import(`./shop/shop.module`).then(m => m.ShopModule) },
  { path: '**', component: BoutiqueComponent }
];

New with Angular 8, loadChildren expects a function that uses the dynamic import syntax to import your lazy-loaded module only when it’s needed. As you can see, the dynamic import is promise-based and gives you access to the module, where the module’s class can be called.

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

  Tweet It

🕵 Search Results

🔎 Searching...

Sponsored by #native_company# — Learn More
#native_title# #native_desc#
#native_cta#