Logo

Angular Performance

Lazy Loading

Don't ship code the user doesn't need. We split the app into small chunks that the browser fetches only on demand.

When I start a new app, it feels blazing fast. But after a few months, I have dozens of features. Suddenly, the main.js is huge, and the user stares at a white screen for 3 seconds.

I treat the startup of my app like a VIP area: Only the essentials (Header, Home) get in immediately. Everything else (Admin, Settings, Charts) has to wait outside (lazy) until the user explicitly asks for it.

1. The Simulation

Watch the "Network Status". When you click on Admin Dashboard, you'll see a brief loading state. That is the exact moment the code is being fetched from the server.

localhost:4200/

Home Page

This component is included in the main.js bundle and immediately available.

2. Implementation

Angular gives us two ways to do this. Which one I choose depends purely on the complexity of the feature I'm building.

Scenario A: The Single Page (loadComponent)

This is my default for isolated pages like "Imprint", "404", or simple dashboards. I tell the router directly: "Just load this one file."

app.routes.ts
// app.routes.ts
export const routes: Routes = [
  {
    path: 'charts',
    // 1. Dynamic Import: The browser fetches this file only when clicked
    // 2. .then(): We extract the component class from the file
    loadComponent: () => import('./charts/charts.component')
      .then(m => m.ChartsComponent)
  }
];

Scenario B: The Feature Area (loadChildren)

This is where it gets interesting. If I have a large area like Settings that has its own sub-pages (Profile, Security, Account), a single component isn't enough.

In this case, I load a separate routing file. This keeps my `app.routes.ts` clean and encapsulates the entire feature.

Step 1: The Parent Router
app.routes.ts
// app.routes.ts
export const routes: Routes = [
  {
    path: 'settings',
    // Here we don't load a component, but a separate ROUTE CONFIGURATION
    loadChildren: () => import('./settings/settings.routes')
      .then(m => m.settingsRoutes)
  }
];
Step 2: The Child Router
settings/settings.routes.ts
// settings/settings.routes.ts (This file is lazy loaded!)
import { Routes } from '@angular/router';

export const settingsRoutes: Routes = [
  // This matches /settings (The entry point)
  {
    path: '',
    component: SettingsOverview
  },
  // This matches /settings/profile
  // The paths are concatenated automatically!
  {
    path: 'profile',
    component: ProfileSettings
  }
];
💡

The Magic of Scenario B: The routes are combined automatically. If I define path: 'settings' in the main router and path: 'profile' in the child router, Angular creates the URL /settings/profile for me.