TL;DR
  • Lazy loading in Angular improves initial load speed by splitting your app into smaller chunks.
  • Use loadChildren for lazy-loading modules; use loadComponent for standalone components.
  • Standalone components cut boilerplate and simplify route configuration.
  • Keep each lazy-loaded feature in its own folder for clarity and maintainability.
  • Preloading strategies optimize navigation speed after the first load.
  • Prefer standalone components for new features; use modules when grouping multiple related components.

Ever notice how your Angular app feels sluggish on first load? That’s probably because you’re loading everything upfront. Lazy loading fixes this by splitting your app into chunks that load only when users actually need them.

Instead of downloading your entire app at once, lazy loading lets you load features on-demand. User clicks “Admin Panel”? That’s when the admin code downloads. Much faster initial loads, happier users.

Angular 19 gives you two ways to lazy load: the traditional module approach and the newer standalone component approach. Let’s see both in action.

Module-Based Lazy Loading

Here’s the classic approach using feature modules:

// app.routes.ts
import { Routes } from '@angular/router';

export const routes: Routes = [
  { path: '', redirectTo: '/home', pathMatch: 'full' },
  { path: 'home', loadChildren: () => import('./home/home.module').then(m => m.HomeModule) },
  { path: 'admin', loadChildren: () => import('./admin/admin.module').then(m => m.AdminModule) },
  { path: '**', redirectTo: '/home' }
];

// home/home.module.ts
import { NgModule } from '@angular/core';
import { RouterModule } from '@angular/router';
import { HomeComponent } from './home.component';

@NgModule({
  declarations: [HomeComponent],
  imports: [
    RouterModule.forChild([
      { path: '', component: HomeComponent }  // Child route within the module
    ])
  ]
})
export class HomeModule { }

Standalone Component Lazy Loading

Now here’s the modern approach with standalone components:

// app.routes.ts
import { Routes } from '@angular/router';

export const routes: Routes = [
  { path: '', redirectTo: '/home', pathMatch: 'full' },
  { path: 'home', loadComponent: () => import('./home/home.component').then(c => c.HomeComponent) },
  { path: 'admin', loadComponent: () => import('./admin/admin.component').then(c => c.AdminComponent) },
  { path: '**', redirectTo: '/home' }
];

// home/home.component.ts
import { Component } from '@angular/core';
import { CommonModule } from '@angular/common';

@Component({
  selector: 'app-home',
  standalone: true,  // This makes it a standalone component
  imports: [CommonModule],  // Import dependencies directly
  template: `<h1>Welcome Home!</h1>`
})
export class HomeComponent { }

Notice how much cleaner the standalone approach is? No module boilerplate, direct imports, and the routing config is simpler.

Key Differences

Module-BasedStandalone Component
Uses loadChildrenUses loadComponent
Requires feature modulesNo modules needed
Child routes defined in moduleRoutes defined directly in main config
More boilerplateCleaner, less code
Good for complex featuresPerfect for simple routes

Folder Structure Tips

Keep your lazy-loaded features organized:

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

Pro tip: Angular’s CLI generates standalone components by default now, so ng generate component admin will create a standalone component ready for lazy loading.

Default Behavior

Angular uses “lazy by default” behavior, routes only load when accessed. But you can add preloading strategies if you want:

// main.ts
bootstrapApplication(AppComponent, {
  providers: [
    provideRouter(routes, withPreloading(PreloadAllModules))  // Preload after initial load
  ]
});

When to Choose What

Go with standalone components for most new features. They’re simpler, have less boilerplate, and work great for straightforward routes.

Stick with modules when you have complex features that need multiple components, services, and guards working together. Modules still make sense for large, self-contained feature areas.

The bottom line? Lazy loading dramatically improves your app’s startup time. Standalone components make it even easier to implement. Start with loadComponent for new features, your users will notice the performance boost immediately.

Frequently Asked Questions

What is lazy loading in Angular and why is it important?

Lazy loading in Angular is a technique where feature modules or components are loaded only when needed, rather than at initial application startup. This reduces the initial bundle size and improves load times, resulting in a faster and more responsive user experience.

How do you implement lazy loading with Angular modules?

Lazy loading with modules uses the loadChildren property in route configuration. For example:

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

This loads the AdminModule only when the user navigates to the /admin route.

What are standalone components in Angular 19?

Standalone components are Angular components that do not require a parent NgModule. They can be imported directly into routes or other components, simplifying project structure and reducing boilerplate. Standalone components are ideal for modern Angular development and lazy loading.

How do you lazy load a standalone component in Angular?

Use the loadComponent property in your route configuration. For example:

{ path: 'home', loadComponent: () => import('./home/home.component').then(c => c.HomeComponent) }

This loads the HomeComponent only when the /home route is accessed.

What are the main differences between module-based and standalone component lazy loading?

Module-based lazy loading uses loadChildren and requires feature modules, while standalone component lazy loading uses loadComponent and does not require modules. Standalone components reduce boilerplate and are better for simple routes, while modules are useful for complex features with multiple dependencies.

When should you use modules instead of standalone components for lazy loading?

Use modules when you have complex features that include multiple components, services, and guards that need to be bundled together. Modules provide clear boundaries and encapsulation for large, self-contained areas of your application.

How does Angular’s default lazy loading behavior work?

By default, Angular loads routes lazily, meaning feature modules or components are loaded only when their route is accessed. This improves initial load performance and reduces the amount of JavaScript downloaded at startup.

What is a preloading strategy in Angular and how do you use it?

A preloading strategy loads lazy routes in the background after the initial app load, improving perceived navigation speed. You can enable it with:

provideRouter(routes, withPreloading(PreloadAllModules))

This preloads all lazy-loaded modules after the app starts.

How should you organize folders for lazy-loaded features in Angular?

Place each lazy-loaded feature in its own folder under src/app/, keeping related components, templates, and styles together. For example:

src/app/
    ├── home/
    ├── admin/
    └── app.routes.ts

What are the benefits of using standalone components for lazy loading in Angular?

Standalone components simplify project structure, reduce boilerplate, and make route configuration cleaner. They are easier to maintain and ideal for new features or simple routes, helping teams adopt modern Angular best practices.
See other angular posts