@defer — Deferred Views

Lazy Load Markup Blocks Without Routing

@defer — Deferred Views

`@defer` downloads a chunk of template only when a trigger fires — viewport, idle, hover, interaction, timer, or immediate.

4 min read Level 2/5 #angular#defer#performance
What you'll learn
  • Use @defer with @placeholder, @loading, and @error blocks
  • Pick the right trigger (on idle, on viewport, on interaction)
  • Combine @defer with @if for conditional lazy content

@defer is route-level lazy loading shrunk down to the markup level. Wrap an expensive block, pick a trigger, and Angular code-splits the components inside into a separate chunk fetched only when needed.

The Four Blocks

@defer (on viewport) {
  <heavy-chart [data]="data()" />
}
@placeholder {
  <div class="chart-skeleton">Chart...</div>
}
@loading (after 100ms; minimum 1s) {
  <spinner />
}
@error {
  <p>Couldn't load the chart.</p>
}
  • @defer wraps the deferred content.
  • @placeholder shows before the trigger fires.
  • @loading shows while the chunk downloads.
  • @error shows if the chunk fails to load.

Triggers

TriggerFires when
on idleBrowser is idle (the default if you omit on)
on viewportBlock scrolls into view
on hoverUser hovers a related element
on interactionUser clicks or taps
on timer(2s)After N seconds
on immediateAs soon as rendering finishes

You can target a specific element with on viewport(trigger) where trigger is a #templateRef.

Prefetch and Combine

prefetch lets you download earlier than you render — for instance, prefetch on hover and render on click.

@defer (on interaction; prefetch on hover) {
  <comments-panel />
}

Combine with @if to defer only when needed: @if (showChart()) { @defer { ... } }. Use it generously around heavy widgets — analytics dashboards, chat panels, rich text editors.

Progressive Web App →