A fast app keeps users and ranks better. Angular's production build already does a lot for you: tree shaking, minification and ahead-of-time compilation. This lesson shows what you control.
What you will learn
- How to build and read the output
- How bundle budgets protect you
- Five habits that keep an Angular app fast
Build for production
ng build
Since Angular 17 the default ng build is a production build. The output goes to dist/<project-name>/browser. Check the table in the terminal: the initial total is what every visitor downloads first. Try to keep it small, and compare after each big change.
Bundle budgets
angular.json has budgets that warn or fail the build when bundles grow too large:
"budgets": [
{ "type": "initial", "maximumWarning": "500kB", "maximumError": "1MB" },
{ "type": "anyComponentStyle", "maximumWarning": "4kB", "maximumError": "8kB" }
]
Treat a budget warning as a signal to find what grew, not as noise.
Five habits
1. Lazy load routes. You did this in the lazy loading lesson.
2. Always use `track` in loops. It lets Angular reuse DOM elements instead of rebuilding the list:
@for (item of items(); track item.id) { ... }
3. Use `OnPush` change detection for components. The component re-checks only when its inputs, signals or events change.
// src/app/perf/fast-badge.ts
import { ChangeDetectionStrategy, Component, input } from '@angular/core';
@Component({
selector: 'app-fast-badge',
changeDetection: ChangeDetectionStrategy.OnPush,
template: `<span class="badge">{{ label() }}</span>`,
})
export class FastBadge {
readonly label = input.required<string>();
}
4. Optimise images with `NgOptimizedImage`. It lazy loads images, sets sizes and warns about common mistakes:
// src/app/perf/hero-image.ts
import { Component } from '@angular/core';
import { NgOptimizedImage } from '@angular/common';
@Component({
selector: 'app-hero-image',
imports: [NgOptimizedImage],
template: `
<img ngSrc="/images/hero.jpg" width="1200" height="600" priority alt="Students learning Angular" />
`,
})
export class HeroImage {}
Use priority only for the one main image at the top of the page. Always set width and height to avoid layout shift.
5. Prefer pure pipes and `computed()` over methods in templates. A method like {{ getTotal() }} runs on every check, while computed() is cached until its inputs change.
Pre-release checklist
ng buildhas no errors and no budget warnings.ng test --watch=falsepasses.- Lighthouse scores are good for Performance, Accessibility and SEO.
- Every page has a unique
title, and public pages have a meta description. - Environment values (API URL) are correct for production.
- No
console.logor secrets are left in the code. Anything in the browser can be read by anyone.
Server-side rendering (SSR)
For public content that must rank in search, add SSR or pre-rendering so the first HTML already contains the content:
ng add @angular/ssr
It is a bigger topic, so add it when SEO or very fast first paint matters. A private dashboard does not need it.
Try it yourself
- Run
ng buildand write down the initial total. - Lazy load one more route and build again. How much did it change?
- Run Lighthouse on your built app and fix the biggest performance warning.
Quick check
- Which
@forpart helps Angular reuse DOM elements? - Why prefer
computed()to a method call in a template? - When should you use the
priorityattribute on an image?
You now have all the building blocks. Time to put them together in the first project: a Task Manager. See the performance guide too.