Make your app resilient and responsive — @defer for lazy template sections with placeholders and loading states, and a global ErrorHandler that catches every crash.
Why: a heavy component the user might never see — a chart, an editor, a comments section — shouldn't be in the initial download. Wrap it in @defer and Angular splits its code out and loads it on a trigger like on viewport (when scrolled into view), with @placeholder before, @loading during, and @error if it fails.
import { Component } from '@angular/core'
import { HeavyChart } from './heavy-chart'
@Component({
selector: 'app-dashboard',
imports: [HeavyChart],
template: `
<h1>Dashboard</h1>
<!-- The chart's code isn't even downloaded until it scrolls into view -->
@defer (on viewport) {
<app-heavy-chart />
} @placeholder {
<p>Chart appears here when you scroll down</p>
} @loading (minimum 300ms) {
<p>Loading chart…</p>
} @error {
<p>Could not load the chart.</p>
}
`,
})
export class Dashboard {}Why: every unhandled error in the app lands in ErrorHandler — one place to log it, report it to a monitoring service, and show the user something better than a frozen screen. Provide your own class once in app.config.ts.
import { ApplicationConfig, ErrorHandler, Injectable } from '@angular/core'
// One place where every unhandled error in the app lands
@Injectable()
export class AppErrorHandler implements ErrorHandler {
handleError(error: unknown) {
// …report to your logging/monitoring service here
console.error('Caught by AppErrorHandler:', error)
}
}
// src/app/app.config.ts — swap in your handler once
export const appConfig: ApplicationConfig = {
providers: [{ provide: ErrorHandler, useClass: AppErrorHandler }],
}