InterviewsVector

Angular @defer: Lazy-Load Template Blocks with Triggers (@placeholder, @loading, @error)

Quick answer

Angular's @defer block lazy-loads a section of a template until a trigger fires — on viewport, on interaction, on hover, on idle (default), on immediate, on timer(...), or when a condition is true. Its component dependencies are split into a separate chunk, so non-critical UI stays out of the initial bundle. Pair it with @placeholder, @loading, and @error blocks to control what renders before, during, and on failure. Note: @defer is a block (@defer { }), not a *defer directive.

Short answer: @defer is a template block (@defer { … }, not a *defer directive) that lazy-loads its content — and code-splits its dependencies — until a trigger fires (on viewport, on interaction, on idle, on hover, on timer, or when a condition). Pair it with @placeholder, @loading, and @error.

@defer is Angular's built-in way to keep non-critical UI out of the initial bundle. The critical detail most write-ups get wrong: it's a block, not a directive — there is no *defer.

Basic usage with all four blocks

@defer (on viewport) {
  <heavy-chart [data]="data" />
} @placeholder {
  <p>Chart loads when you scroll to it</p>
} @loading (minimum 1s) {
  <spinner />
} @error {
  <p>Couldn't load the chart.</p>
}
  • @defer — the deferred content; its components are split into a separate chunk.
  • @placeholder — shown until the trigger fires (required to use the on viewport/on interaction/on hover triggers).
  • @loading — shown while the chunk downloads; minimum/after params prevent spinner flicker.
  • @error — shown if loading fails.

Triggers

@defer (on idle)            { … }   <!-- default: when the browser is idle -->
@defer (on viewport)        { … }   <!-- placeholder scrolls into view -->
@defer (on interaction)     { … }   <!-- user clicks/keys the placeholder -->
@defer (on hover)           { … }   <!-- pointer over the placeholder -->
@defer (on immediate)       { … }   <!-- as soon as rendering finishes -->
@defer (on timer(5s))       { … }   <!-- after a delay -->
@defer (when isReady())     { … }   <!-- when a condition becomes true -->

Prefetch: download early, render later

Fetch the chunk ahead of time without rendering it yet, so it's ready the instant the trigger fires:

@defer (on interaction; prefetch on idle) {
  <comments-panel />
} @placeholder {
  <button>Show comments</button>
}

Trade-offs and the SEO caveat

  • Reduced initial bundle / faster first load — the deferred chunk isn't downloaded until needed.
  • SEO caveat — deferred content is not in the initial render, so crawlers may not see it until the trigger fires. Defer genuinely non-critical, below-the-fold UI; keep must-index content outside @defer.
  • Standalone deps — the components inside @defer should only be referenced there, so Angular can safely split them into their own chunk.

Common interview traps

  • <div *defer> — invalid; @defer is a block, not a directive.
  • Forgetting @placeholder — required for the interaction/viewport/hover triggers.
  • Deferring above-the-fold or must-index content — hurts UX/SEO.

Sources

Key takeaways

  • @defer is a template BLOCK — @defer { } — not a *defer directive (that syntax does not exist).
  • Triggers: on idle (default), on viewport, on interaction, on hover, on immediate, on timer(5s), or when <condition>.
  • Deferred dependencies are code-split into their own chunk, shrinking the initial bundle.
  • @placeholder, @loading, and @error blocks control the before/during/failure UI; @loading and @placeholder take timing params.
  • Use prefetch (e.g. prefetch on idle) to fetch the chunk early but render it later; and remember deferred content isn't in the initial render (SEO caveat).

Frequently asked questions

What is @defer in Angular used for?

@defer lazily loads a block of a template — and code-splits its component dependencies into a separate JavaScript chunk — until a trigger fires. It keeps non-critical content (charts, comments, below-the-fold widgets) out of the initial bundle, improving initial load time.

What triggers can @defer use?

on idle (the default), on viewport (when the placeholder enters the viewport), on interaction, on hover, on immediate, on timer(duration), and when <boolean expression>. You can also add prefetch with its own trigger to download the chunk ahead of rendering.

Does @defer hurt SEO?

It can for the deferred content specifically, because that content is not in the server-rendered/initial HTML — a crawler may not see it until the trigger fires. Defer genuinely non-critical, below-the-fold UI; keep content you need indexed outside the @defer block.

By Mohammad Wasi

Software Engineering Leader & Technical Author · Updated August 26, 2026


Related Posts