← Back to Articles         
What is lazy loading?

What is lazy loading?

Published on 02 Oct 2026     7 min read Angular
Lazy Loading

What is Lazy Loading in Angular?

1. What is Lazy Loading?

Lazy loading is a technique where Angular loads a feature, component, or route only when the user needs or navigates to it, instead of loading everything when the application starts.

In simple terms:

Lazy Loading = Load it when needed, not at application startup.

For example, suppose an application has these pages:

Home
Products
Orders
Admin
Reports

Without lazy loading:

Application Starts
       ↓
Load Home
Load Products
Load Orders
Load Admin
Load Reports
       ↓
Application Ready

With lazy loading:

Application Starts
       ↓
Load Home only

User clicks Products
       ↓
Load Products

User clicks Admin
       ↓
Load Admin

This reduces the initial JavaScript bundle that the browser must download and process.


2. Full Simple Sample Program

In modern standalone Angular, loadComponent() is commonly used to lazy-load a standalone component.

Project structure

src/app/
│
├── app.ts
├── app.html
├── app.routes.ts
│
├── home/
│   ├── home.ts
│   └── home.html
│
├── products/
│   ├── products.ts
│   └── products.html
│
└── admin/
    ├── admin.ts
    └── admin.html

app.routes.ts

import { Routes } from '@angular/router';
import { Home } from './home/home';

export const routes: Routes = [
  {
    path: '',
    component: Home
  },
  {
    path: 'products',
    loadComponent: () =>
      import('./products/products')
        .then(m => m.Products)
  },
  {
    path: 'admin',
    loadComponent: () =>
      import('./admin/admin')
        .then(m => m.Admin)
  }
];

app.ts

import { Component } from '@angular/core';
import { RouterLink, RouterOutlet } from '@angular/router';

@Component({
  selector: 'app-root',
  standalone: true,
  imports: [RouterLink, RouterOutlet],
  templateUrl: './app.html'
})
export class App {
}

app.html

<h1>My Angular Application</h1>

<nav>
  <a routerLink="/">Home</a> |
  <a routerLink="/products">Products</a> |
  <a routerLink="/admin">Admin</a>
</nav>

<hr>

<router-outlet></router-outlet>

home/home.ts

import { Component } from '@angular/core';

@Component({
  selector: 'app-home',
  standalone: true,
  templateUrl: './home.html'
})
export class Home {
}

home/home.html

<h2>Home</h2>

<p>Welcome to the application.</p>

products/products.ts

import { Component } from '@angular/core';

@Component({
  selector: 'app-products',
  standalone: true,
  templateUrl: './products.html'
})
export class Products {
}

products/products.html

<h2>Products</h2>

<p>Products page loaded successfully.</p>

admin/admin.ts

import { Component } from '@angular/core';

@Component({
  selector: 'app-admin',
  standalone: true,
  templateUrl: './admin.html'
})
export class Admin {
}

admin/admin.html

<h2>Admin</h2>

<p>Admin page loaded successfully.</p>

3. Explanation

The important code is:

{
  path: 'products',
  loadComponent: () =>
    import('./products/products')
      .then(m => m.Products)
}

Notice that we didn't import Products at the top of app.routes.ts.

We did not write:

import { Products } from './products/products';

Instead, Angular uses dynamic import():

import('./products/products')

This tells the bundler that the Products feature can be split into a separate chunk.

When the user navigates to:

/products

Angular loads that chunk and then uses:

.then(m => m.Products)

to retrieve the Products component.


4. Normal Loading vs Lazy Loading

Eager loading

import { Products } from './products/products';

export const routes: Routes = [
  {
    path: 'products',
    component: Products
  }
];

Here, Products is statically imported and is part of the application's eagerly reachable code.

Conceptually:

Application starts
       ↓
Main application code
       +
Products
       ↓
Application runs

Lazy loading

{
  path: 'products',
  loadComponent: () =>
    import('./products/products')
      .then(m => m.Products)
}

Conceptually:

Application starts
       ↓
Initial application code

          Later...

User → /products
       ↓
Products chunk downloaded
       ↓
Products component displayed

5. loadComponent() vs loadChildren()

There are two important lazy-loading mechanisms in Angular routing.

loadComponent()

Used to lazy-load a standalone component.

{
  path: 'products',
  loadComponent: () =>
    import('./products/products')
      .then(m => m.Products)
}

This is ideal for a single standalone route component.


loadChildren()

Used to lazy-load a group of routes.

For example:

admin/
├── admin.routes.ts
├── dashboard.ts
├── users.ts
└── reports.ts

Main routes:

export const routes: Routes = [
  {
    path: 'admin',
    loadChildren: () =>
      import('./admin/admin.routes')
        .then(m => m.ADMIN_ROUTES)
  }
];

admin/admin.routes.ts:

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

export const ADMIN_ROUTES: Routes = [
  {
    path: 'dashboard',
    loadComponent: () =>
      import('./dashboard')
        .then(m => m.Dashboard)
  },
  {
    path: 'users',
    loadComponent: () =>
      import('./users')
        .then(m => m.Users)
  }
];

Now the entire Admin route configuration is loaded only when the user enters:

/admin/...

6. Before Standalone Angular

Traditionally, Angular applications commonly lazy-loaded NgModules.

For example:

{
  path: 'products',
  loadChildren: () =>
    import('./products/products.module')
      .then(m => m.ProductsModule)
}

The structure might have been:

products/
├── products.module.ts
├── products-routing.module.ts
├── products.component.ts
└── products.component.html

The lazy-loading unit was typically the feature module.


7. Modern Standalone Angular

Standalone Angular does not require an NgModule just to lazy-load a feature.

You can lazy-load a component directly:

{
  path: 'products',
  loadComponent: () =>
    import('./products/products')
      .then(m => m.Products)
}

Or lazy-load a route collection:

{
  path: 'admin',
  loadChildren: () =>
    import('./admin/admin.routes')
      .then(m => m.ADMIN_ROUTES)
}

So the evolution is roughly:

Traditional Angular

Route
  ↓
loadChildren()
  ↓
Feature NgModule
  ↓
Component

Modern standalone Angular:

Route
  ↓
loadComponent()
  ↓
Standalone Component

or:

Route
  ↓
loadChildren()
  ↓
Routes
  ↓
Standalone Components

8. Why is Lazy Loading Important?

Consider a large application:

Home        300 KB
Products    500 KB
Orders      400 KB
Admin       600 KB
Reports     500 KB

Without code splitting/lazy loading, much more code may be needed during initial startup.

Conceptually:

Initial Download
      ↓
Home
Products
Orders
Admin
Reports

With lazy loading:

Initial Download
      ↓
Core/Home

/products
      ↓
Products chunk

/admin
      ↓
Admin chunk

The exact bundle sizes and splitting depend on the build, but the key idea is that code for lazy routes can be deferred until needed.


9. Advantages

Lazy loading can provide:

  • Smaller initial bundle
  • Faster initial startup
  • Less JavaScript to initially download, parse, and execute
  • Better scalability for large applications
  • Logical separation of application features
  • Users don't immediately download code for features they never visit

It is especially useful for areas such as:

Admin
Reports
Settings
Orders
Analytics
Management screens

10. Key Points

Concept Meaning
Lazy Loading Load code only when needed
Eager Loading Code is part of the eagerly loaded dependency graph
loadComponent() Lazy-load a standalone component
loadChildren() Lazy-load child routes/feature route configuration
import() Dynamic import enabling code splitting
Main benefit Reduce initial JavaScript workload
Traditional Angular Commonly lazy-loaded feature NgModules
Modern Angular Can lazy-load standalone components and route collections

A useful interview definition is:

Lazy loading in Angular is a technique that loads feature code only when it is required, typically when the user navigates to a route. It reduces the initial bundle size and can improve application startup performance.

11. Interview Questions and Answers

1. What is lazy loading in Angular?

Lazy loading means loading a feature or component only when it is required, instead of including all feature code in the initial application load.


2. Why do we use lazy loading?

Primarily to reduce the application's initial JavaScript workload and improve startup performance, especially in large applications.


3. How do you lazy-load a standalone component?

Using loadComponent():

{
  path: 'products',
  loadComponent: () =>
    import('./products/products')
      .then(m => m.Products)
}

4. What is loadChildren()?

loadChildren() lazy-loads a set of child routes or, in older Angular architectures, a feature NgModule.

{
  path: 'admin',
  loadChildren: () =>
    import('./admin/admin.routes')
      .then(m => m.ADMIN_ROUTES)
}

5. What is the difference between loadComponent() and loadChildren()?

loadComponent()
      ↓
Single standalone component

loadChildren()
      ↓
Collection of routes / feature area

6. What is the difference between eager loading and lazy loading?

Eager loading makes feature code reachable from the initial application dependency graph.

Lazy loading splits feature code so it can be fetched later when the route is accessed.


7. How was lazy loading implemented before standalone Angular?

It was commonly implemented by lazy-loading an NgModule:

loadChildren: () =>
  import('./products/products.module')
    .then(m => m.ProductsModule)

8. Does lazy loading mean the page is loaded from ASP.NET Core Web API?

No.

These are separate concepts:

Lazy Loading
    ↓
Loads Angular JavaScript/code

HttpClient
    ↓
Loads data from ASP.NET Core Web API

For example:

User opens /products
        ↓
Angular lazy-loads Products component
        ↓
Products component starts
        ↓
HttpClient
        ↓
ASP.NET Core Web API
        ↓
SQL Server
        ↓
Product data returned

This distinction is particularly important in an Angular + ASP.NET Core Web API architecture.

← Back to Articles