Performance & Lazy Loading

5 questions found

What is lazy loading in Angular and why is it useful for performance?

Beginner
Lazy loading means only downloading the code for a specific feature or route when the user actually navigates to it, instead of including everything in the app's initial bundle. This makes the very first page load faster, since the browser only needs to download the code it actually needs right away.
const routes: Routes = [
  { path: 'orders', loadChildren: () => import('./orders/orders.routes') }
];
// The orders feature's code is only downloaded when a user visits the orders route
Real-world example A large admin panel only downloads the code for its rarely visited reports section the first time a user actually navigates there, thanks to lazy loading that specific feature, keeping the initial page load fast for everyone.

Common follow-ups: How much smaller does an app's initial load usually get after adding lazy loading?;What tool shows you how big each lazy loaded chunk actually is?

Routing;Build Environments & Deployment

How does the OnPush change detection strategy improve performance in a large Angular application?

Intermediate
OnPush tells Angular to only check a component when its inputs change by reference, an event happens inside it, or an observable it depends on emits, rather than checking it on every single change detection cycle throughout the app. This meaningfully reduces unnecessary work in apps with many components.
@Component({
  selector: 'app-product-card',
  changeDetection: ChangeDetectionStrategy.OnPush,
  template: `<p>{{ product.name }}</p>`
})
export class ProductCardComponent {
  @Input() product!: Product;
}
Real-world example A large product listing page noticeably speeds up after applying OnPush to every individual product card component, since Angular no longer needs to unnecessarily check every single card on every user interaction elsewhere on the page.

Common follow-ups: What specifically needs to change for OnPush to correctly detect an update to an input object?;How do signals help make this optimization even more automatic?

Change Detection;Angular Signals

How would you use Angular's built in deferred loading, the at defer block, to improve performance further?

Advanced
The at defer block lets you delay loading and rendering a piece of a template until a specific trigger happens, such as the element becoming visible on screen, the user interacting with a nearby element, or after the browser becomes idle, reducing the amount of work done during the initial page load.
@Component({
  selector: 'app-product-page',
  template: `
    <app-product-details [product]="product" />
    @defer (on viewport) {
      <app-related-products />
    } @placeholder {
      <p>Loading recommendations</p>
    }
  `
})
export class ProductPageComponent {}
Real-world example A product page loads its main details immediately, but defers loading a lower priority related products section until it actually scrolls into view, speeding up the initial page load noticeably.

Common follow-ups: What other trigger conditions besides viewport does the at defer block support?;How does at defer compare to manually lazy loading a component with React.lazy or similar in other frameworks?

New Control Flow Syntax (@if @for & @switch);Components & Templates

How does using trackBy, or the track expression in the newer at for syntax, improve the performance of rendering lists?

Intermediate
Without a tracking expression, Angular assumes every item in a list might be a completely different one whenever the list reference changes, potentially destroying and recreating every single element unnecessarily. Providing a unique identifier lets Angular correctly match existing elements to the same underlying data, updating only what actually changed instead of rebuilding the entire list.
@for (product of products; track product.id) {
  <app-product-card [product]="product" />
}
// Angular reuses existing elements correctly instead of recreating the entire list
Real-world example A product catalog page avoids unnecessarily destroying and recreating every single product card whenever the underlying list is refreshed with mostly the same products, thanks to tracking each item by its unique product id.

Common follow-ups: What happens if you use the array index as the tracking value instead of a genuinely unique id?;How much of a real performance difference does this make for a list with thousands of items?

New Control Flow Syntax (@if @for & @switch);Directives

How do you check your Angular app's actual bundle size and find opportunities to reduce it?

Beginner
You build your app for production and use a bundle analysis tool, like source-map-explorer, to visualize exactly which packages and files are taking up the most space, helping you spot unnecessarily large dependencies or code that could be lazy loaded instead of included upfront.
ng build --configuration production
npx source-map-explorer dist/my-app/*.js
// opens a visual chart showing which packages take up the most space
Real-world example A team discovers a large unused charting library was accidentally being included in their main bundle, using source-map-explorer to visualize the bundle after a production build, and removes it to significantly reduce load time.

Common follow-ups: What is a reasonable initial bundle size target for a typical Angular app?;How would you set a bundle size budget that fails the build if exceeded?

Build Environments & Deployment;Angular CLI & Project Structure