← Back to Articles         
loadChildren() vs loadComponent()

loadChildren() vs loadComponent()

Published on 02 Oct 2026     8 min read Angular
Lazy Loading

Angular Lazy Loading: Standalone Components, loadChildren() and loadComponent()

In modern standalone Angular, lazy loading is simpler because we do not need to create an NgModule just to lazy-load a component.

The two important router APIs are:

loadComponent() → Lazy-load ONE standalone component

loadChildren()  → Lazy-load a GROUP of routes

1. How Is Lazy Loading Implemented with Standalone Components?

What is it?

With standalone components, Angular can lazy-load a component directly through the router using:

loadComponent()

For example:

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

When the application starts, the Products component isn't part of that route's eager import.

When the user navigates to:

/products

Angular dynamically loads the component.


Full Simple Sample Program

Project Structure

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

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)
  }
];

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 Application</h1>

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

<hr>

<router-outlet></router-outlet>

home/home.ts

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

@Component({
  selector: 'app-home',
  standalone: true,
  template: `
    <h2>Home</h2>
    <p>Welcome to Home.</p>
  `
})
export class Home {
}

products/products.ts

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

@Component({
  selector: 'app-products',
  standalone: true,
  template: `
    <h2>Products</h2>

    <ul>
      <li>Laptop</li>
      <li>Keyboard</li>
      <li>Mouse</li>
    </ul>
  `
})
export class Products {
}

How Does It Work?

When the application starts:

Application starts
      ↓
Home loaded
      ↓
Products not loaded yet

When the user clicks:

Products

Angular navigates to:

/products

The router finds:

loadComponent: () =>
  import('./products/products')
    .then(m => m.Products)

Then:

User → /products
        ↓
Angular Router
        ↓
loadComponent()
        ↓
Dynamic import()
        ↓
Products component loaded
        ↓
Products displayed

The important point is that the component isn't statically imported into app.routes.ts.

We don't do:

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

for this lazy route.


2. What is loadComponent()?

What is it?

loadComponent() is an Angular Router route property used to lazy-load a single standalone component.

Example:

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

Think:

loadComponent() = load one component when its route is needed.


loadComponent() Flow

/products
    ↓
loadComponent()
    ↓
products.ts downloaded/loaded
    ↓
Products
    ↓
<router-outlet>

Eager Component vs Lazy Component

Eager

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

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

Because Products is statically imported:

Application
    ↓
Products reachable eagerly

Lazy

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

Now:

Application starts
      ↓
Products code deferred

User → /products
      ↓
Products code loaded

3. What is loadChildren()?

What is it?

loadChildren() is an Angular Router property used to lazy-load child routes / a group of routes.

In modern standalone Angular, it is very useful when a feature contains multiple pages.

For example, suppose Admin contains:

Admin
│
├── Dashboard
├── Users
└── Reports

Instead of putting every Admin route in the main app.routes.ts, we can create:

admin.routes.ts

and lazy-load the entire route collection.


Full loadChildren() Example

Project Structure

src/app/
│
├── app.ts
├── app.routes.ts
│
└── admin/
    │
    ├── admin.routes.ts
    ├── dashboard.ts
    ├── users.ts
    └── reports.ts

app.routes.ts

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

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)
  },
  {
    path: 'reports',
    loadComponent: () =>
      import('./reports')
        .then(m => m.Reports)
  }
];

admin/dashboard.ts

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

@Component({
  selector: 'app-dashboard',
  standalone: true,
  template: `
    <h2>Admin Dashboard</h2>
    <p>Welcome to Admin Dashboard.</p>
  `
})
export class Dashboard {
}

admin/users.ts

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

@Component({
  selector: 'app-users',
  standalone: true,
  template: `
    <h2>Users</h2>
    <p>User management page.</p>
  `
})
export class Users {
}

admin/reports.ts

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

@Component({
  selector: 'app-reports',
  standalone: true,
  template: `
    <h2>Reports</h2>
    <p>Admin reports page.</p>
  `
})
export class Reports {
}

How loadChildren() Works

Suppose the user enters:

/admin/users

Angular first sees:

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

It lazy-loads:

admin.routes.ts

Then Angular looks inside:

ADMIN_ROUTES

and finds:

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

Then it loads the Users component.

So:

/admin/users
      ↓
app.routes.ts
      ↓
path: 'admin'
      ↓
loadChildren()
      ↓
admin.routes.ts
      ↓
path: 'users'
      ↓
loadComponent()
      ↓
Users

This shows how loadChildren() and loadComponent() can work together.


loadChildren() Does NOT Mean "Load Child Components"

This is an important interview point.

The name can be confusing.

loadChildren() doesn't simply mean:

Load child components.

It means:

Lazy-load child route configuration / a feature routing boundary.

For example:

loadChildren: () =>
  import('./admin/admin.routes')
    .then(m => m.ADMIN_ROUTES)

The returned value is:

Routes

Traditional loadChildren() vs Modern loadChildren()

This is particularly important because the meaning has evolved with standalone Angular.

Traditional NgModule Angular

loadChildren() commonly loaded an NgModule.

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

Flow:

loadChildren()
      ↓
ProductsModule
      ↓
ProductsRoutingModule
      ↓
ProductsComponent

Modern Standalone Angular

loadChildren() can lazy-load a route collection.

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

Flow:

loadChildren()
      ↓
ADMIN_ROUTES
      ↓
Dashboard
Users
Reports

Therefore:

Before standalone
loadChildren()
      ↓
Feature NgModule

Modern standalone
loadChildren()
      ↓
Routes / feature route configuration

loadComponent() vs loadChildren()

This is the main distinction to remember.

loadComponent() loadChildren()
Loads one component Loads child routes / route collection
Best for individual page Best for feature area
Common with standalone components Works with standalone routes and traditional NgModules
Returns a component type Can return routes or a lazy-loaded module
Example: Products page Example: Admin feature

Think of it like:

ONE PAGE
   ↓
loadComponent()

MULTIPLE RELATED ROUTES
   ↓
loadChildren()

Practical Example

Suppose your application has:

Home
Articles
Contact

Admin
 ├── Dashboard
 ├── Articles
 ├── Categories
 └── Tags

A sensible routing structure could be:

export const routes: Routes = [
  {
    path: '',
    loadComponent: () =>
      import('./home/home')
        .then(m => m.Home)
  },

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

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

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

Here:

Home
    → loadComponent()

Articles
    → loadComponent()

Contact
    → loadComponent()

Admin feature
    → loadChildren()
         ↓
       Dashboard
       Articles
       Categories
       Tags

This is a useful pattern for a standalone Angular frontend with multiple feature areas.


Key Points

  1. Standalone Angular doesn't require an NgModule just to lazy-load a component.

  2. Use:

loadComponent()

to lazy-load one standalone component.

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

to lazy-load a feature's child routes.

  1. Example:
{
  path: 'admin',
  loadChildren: () =>
    import('./admin/admin.routes')
      .then(m => m.ADMIN_ROUTES)
}
  1. loadChildren() is not obsolete in standalone Angular.

  2. Traditional Angular commonly used loadChildren() for:

Feature NgModule
  1. Modern standalone Angular commonly uses it for:
Feature Routes
  1. A common modern design is:
Individual Page
      ↓
loadComponent()

Feature with many routes
      ↓
loadChildren()

Interview Questions and Answers

1. How is lazy loading implemented with standalone components?

Standalone components can be lazy-loaded directly using the Angular Router's loadComponent() property.

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

2. What is loadComponent()?

loadComponent() lazy-loads a single standalone component when its route is accessed.

loadComponent: () =>
  import('./products/products')
    .then(m => m.Products)

3. What is loadChildren()?

loadChildren() lazy-loads child routing configuration or, in traditional Angular applications, a feature NgModule.

Modern example:

loadChildren: () =>
  import('./admin/admin.routes')
    .then(m => m.ADMIN_ROUTES)

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

loadComponent() is generally used for a single standalone component.

loadChildren() is generally used for a feature containing multiple child routes.


5. Is loadChildren() only for NgModules?

No.

Traditionally:

loadChildren()
      ↓
NgModule

Modern standalone Angular:

loadChildren()
      ↓
Routes

6. Can loadChildren() and loadComponent() be used together?

Yes. This is a common standalone routing pattern.

App Routes
    ↓
loadChildren()
    ↓
Admin Routes
    ↓
loadComponent()
    ↓
Users

For example:

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

and inside Admin:

// admin.routes.ts
{
  path: 'users',
  loadComponent: () =>
    import('./users')
      .then(m => m.Users)
}

Quick interview memory

loadComponent()
     =
Lazy-load ONE standalone component


loadChildren()
     =
Lazy-load a GROUP of routes
     |
     +-- Dashboard
     +-- Users
     +-- Reports

Traditional Angular: loadChildren() → Feature NgModule

Modern standalone Angular: loadChildren() → Feature routes, while loadComponent() → individual standalone component.

← Back to Articles