25. Angular performance optimisation
Answer as submitted
“Yes — performance tuning on large Angular applications is a documented part of my practice.”
Expanded answer
Yes, and always in the same order: measure first (Angular DevTools profiler plus field LCP, INP and CLS), then fix change detection (OnPush across presentational components, signals and pure pipes instead of template function calls, detached detection for high-frequency widgets), then rendering cost (stable track in @for, virtual scrolling for long lists, @defer for heavy panels), then the bundle (route-level splitting, budgets in the build, dependency review), and finally memory (every subscription, listener, timer and cache released with the component). A change is only accepted with a number attached, measured on a throttled CPU and a slow network.
| Area | What is changed | Measured effect |
|---|---|---|
| Change detection | OnPush, signals, pure pipes, no template calls | 412 → 37 checks per interaction; 2 of 40 components re-render on a row update. |
| Rendering | track, virtual scroll, @defer | 1,240 → 42 DOM nodes for the same list. |
| Bundle | route splitting, budgets, dependency review | 210 → 78 KB gzip initial; +52 KB recovered from one dependency swap. |
| Measurement | profiler + PerformanceObserver in production | LCP 3.4 → 1.2 s under 4× CPU throttling; INP 340 → 96 ms. |
| Memory | lifecycle-bound teardown, bounded caches | 0 detached nodes after 20 navigations; 18 MB heap drift removed. |
| Guard rails | budgets in CI, regression alarm on vitals | A performance regression fails the build or raises an alert, not a ticket. |
Live Angular performance workflow proof
The running component below changes its technique/result view through real event binding. Select a step to see what is changed, the reasoning behind it, and the measured before/after.
Choose an optimisation step
Select a step to inspect the change, the reasoning and the measured result.
$ changeDetection: OnPush + signals/computed + pure pipes — no template function calls
Change detection runs only when something actually changes: OnPush everywhere, signals for derived values, pure pipes instead of template methods, and detached detection for high-frequency widgets.
checks per interaction: 412 → 37 components re-rendered on one row update: 2 of 40
How optimisation is kept honest
Source files
Select a file to inspect the proof with syntax highlighting and line numbers. The first file is the code running the component above; the other two are the production shapes of these techniques.
Acceptance criteria
- Covers change detection, rendering, bundle, measurement and memory.
- Attaches a before/after number to every change claimed.
- Shows an interactive proof of choosing an optimisation step and reading its result.
- Keeps budgets in the build so a regression cannot ship silently.
- Defers SSR strategy, CDN configuration and backend tuning to a later topic.