Angular Lazy Loading: Step-by-Step Guide

Lazy loading delays loading non-essential Angular modules until needed, improving app performance and user experience. Here’s the quick breakdown:

  • What is Lazy Loading?
    It loads modules only when required, reducing initial load time and memory usage.
  • Why Use It?

    • Faster app startup
    • Efficient use of resources
    • Better user experience
  • How to Implement It?

    1. Create feature modules with their own routing.
    2. Use loadChildren in the main routing file.
    3. Test with Chrome DevTools to confirm dynamic module loading.

Lazy loading is perfect for large features, admin sections, and dashboards. Follow this guide to make your Angular app faster and more efficient today!

Angular 18 Lazy Loading Guide: Traditional vs. Standalone …

Angular

Setting Up Your Angular Project

Organize your Angular app by breaking it into feature modules, which makes lazy loading easier and keeps your code manageable.

Building Feature Modules

Feature modules should focus on a single responsibility and include their own routing. Here’s what each module should do:

  • Group together related components, services, and routes.
  • Focus on one specific task or responsibility.
  • Work independently from other feature modules.
  • Define its own routing setup.

For example, in an e-commerce app, you might create these feature modules:

// Product module
ng generate module products --routing
// Cart module
ng generate module shopping-cart --routing
// User profile module
ng generate module user-profile --routing

Each module should follow a clear directory structure, like this:

src/app/
├── products/
│   ├── products.module.ts
│   ├── products-routing.module.ts
│   └── components/
├── shopping-cart/
│   ├── shopping-cart.module.ts
│   ├── shopping-cart-routing.module.ts
│   └── components/
└── user-profile/
    ├── user-profile.module.ts
    ├── user-profile-routing.module.ts
    └── components/

Setting Up Route Configuration

In your main routing file (app-routing.module.ts), set up the routes like this:

// app-routing.module.ts
const routes: Routes = [
  { path: '', component: HomeComponent },
  {
    path: 'products',
    loadChildren: () => import('./products/products.module')
      .then(m => m.ProductsModule)
  },
  {
    path: 'cart',
    loadChildren: () => import('./shopping-cart/shopping-cart.module')
      .then(m => m.ShoppingCartModule)
  }
];

Each feature module should handle its own routing. For example, the products-routing.module.ts might look like this:

// products-routing.module.ts
const routes: Routes = [
  {
    path: '',
    component: ProductListComponent,
    children: [
      { path: ':id', component: ProductDetailComponent }
    ]
  }
];

Key Configuration Tips:

  • Don’t import feature modules in app.module.ts.
  • Use RouterModule.forChild(routes) inside feature modules.
  • Keep RouterModule.forRoot(routes) in the main module.
  • Choose the right path-matching strategies for your routes.

Once you’ve set up the structure and configured the routes, you’re ready to implement lazy loading in your Angular project.

Implementing Lazy Loading: Step by Step

With our project structure ready, let’s walk through how to set up lazy loading in an Angular application.

Step 1: Create a Module and Set Up Routes

First, generate a new feature module with routing:

ng generate module admin --routing

Then, configure the module:

@NgModule({
  declarations: [
    AdminDashboardComponent,
    UserManagementComponent
  ],
  imports: [
    CommonModule,
    AdminRoutingModule
  ]
})
export class AdminModule { }

Step 2: Define Lazy Routes

Next, set up internal routes for the feature module in admin-routing.module.ts:

const routes: Routes = [
  {
    path: '',
    component: AdminDashboardComponent,
    children: [
      {
        path: 'users',
        component: UserManagementComponent
      }
    ]
  }
];

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

These routes will handle navigation within the feature module.

Step 3: Update the Main Routes

Now, modify the main routing file (app-routing.module.ts) to load the module lazily:

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

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

This ensures the AdminModule is loaded only when the admin route is accessed.

Step 4: Build and Connect Components

Finally, build the components for the module and link them to the routes. For example, here’s the AdminDashboardComponent:

@Component({
  selector: 'app-admin-dashboard',
  template: `
    <div class="admin-container">
      <router-outlet></router-outlet>
    </div>
  `
})
export class AdminDashboardComponent {
  // Add component logic here
}

Make sure to declare components, register any required services, and import necessary Angular modules. Test the routing to ensure everything is working as expected.

Verify Lazy Loading

To confirm lazy loading is working:

  1. Open Chrome DevTools and go to the Network tab.
  2. Navigate to a lazy-loaded route (e.g., /admin).
  3. Check for a new JavaScript bundle (e.g., admin-module.js) being downloaded.

If you see the bundle loading dynamically, congratulations – you’ve successfully implemented lazy loading! This approach helps reduce the initial bundle size and improves performance.

sbb-itb-608da6a

Lazy Loading Best Practices

Deciding What to Lazy Load

In Angular applications, lazy loading works best when applied to modules that aren’t needed immediately upon startup. Here are some examples of modules that are ideal for lazy loading:

  • Large feature modules: These modules often contain extensive functionality that users don’t need right away.
  • Admin sections: Typically accessed by specific users, these can be loaded only when needed.
  • Complex dashboards: Dashboards with heavy dependencies can benefit from being loaded on demand.
  • Report generation modules: These often combine various components and services, making them a good candidate for lazy loading.

Preventing Common Mistakes

Setting up lazy loading can be tricky, especially when it comes to routing. To avoid common pitfalls, follow these tips:

  • Use "loadChildren" for lazy-loaded routes instead of "children."
  • Double-check the path configurations in both parent and child routing modules to ensure they align.
  • Assign unique path names to each feature module to prevent conflicts.

Testing Lazy Loading Setup

After setting up lazy loading, it’s important to confirm everything works as expected by running some targeted tests.

Using DevTools

Chrome DevTools can help you check if lazy loading is functioning correctly. Here’s how to monitor bundle loading:

  • Open your application in Chrome.
  • Press F12 to launch DevTools.
  • Go to the Network tab.
  • Filter requests by "JS."
  • Clear the network log.
  • Navigate to a route that uses lazy loading.

You should see separate module bundles in the network requests, named something like src_app_feature_feature.module.js or similar chunk names.

Measuring Speed Improvements

To confirm lazy loading is improving performance, use the Performance tab in Chrome:

  • Check Initial Bundle Size: Compare the size of the main.js file before and after enabling lazy loading.
  • Track Load Time: Look at the Time to Interactive (TTI) metric.
  • Analyze Network Requests: Use the waterfall chart to confirm that chunks are loading as expected.

For a deeper look at your bundles, run the following command:

ng build --stats-json && webpack-bundle-analyzer dist/stats.json

This generates a visual breakdown of your bundle sizes and how they’re distributed.

If your performance metrics don’t look right, move on to troubleshooting.

Fixing Common Problems

Here are some common lazy loading issues and how to address them:

  • Module Not Loading
    Double-check your route configuration:

    const routes: Routes = [
      {
        path: 'feature',
        loadChildren: () => import('./feature/feature.module')
          .then(m => m.FeatureModule)
      }
    ];
    
  • Circular Dependencies
    Use Angular’s dependency analyzer to spot circular dependencies:

    ng serve --configuration=development --sourcemap
    
  • Performance Monitoring
    Keep an eye on performance metrics to ensure the setup is working as intended.

Key areas to review include:

  • Route configuration and syntax.
  • Module import paths.
  • Bundle size and distribution.
  • Patterns in network requests.

Summary

The techniques and practices covered above help set up lazy loading effectively in Angular applications. By dividing your code into smaller, on-demand chunks, lazy loading reduces the initial bundle size and improves load times.

To put these practices into action:

  • Break your application into well-defined feature modules.
  • Use the loadChildren syntax to configure routes correctly.
  • Keep an eye on bundle sizes and loading patterns with Chrome DevTools.
  • Test your application under various network conditions to ensure reliability.

A properly implemented lazy loading setup keeps your Angular app responsive and efficient, even as it becomes more complex. Regularly track performance metrics and maintain a clean module structure to continue reaping the benefits over time.

Related Blog Posts

Design. Development. Management.


When you want the best, you need specialists.

Book Consult
To top