What’s actually slowing this PC down?

Pick the symptom - the matching free tool is one click away.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

iTechGuides is reader-supported. When you buy through links on our site, we may earn an affiliate commission. As an Amazon Associate I earn from qualifying purchases. Learn more

Angular’s @defer block lets you keep parts of a template out of the initial load and fetch their code only when a trigger fires or a condition becomes true. It reduces the amount of code a page must download before first render, but only when the deferred content is not needed for that first render. Whether it improves a given app’s measured performance depends on the app, so treat it as a loading decision you verify, not a guaranteed speed gain.

What a deferrable view does

A deferrable view is the content wrapped in a @defer block. Angular splits the eligible components, directives, pipes, and their component CSS into separately loaded code. The compiler turns those dependencies into dynamic imports, and the block renders once the imports resolve. The Angular deferred loading guide describes this behavior, and the @defer API reference lists the trigger and option syntax. The guide does not guarantee the order in which those imports resolve, so your code should not depend on it.

Basic syntax

A minimal block wraps the content whose dependencies can wait. The optional state blocks handle what the user sees before and during loading:

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
@defer {
  <large-component />
} @placeholder {
  <p>Content will load when needed.</p>
} @loading (after 100ms; minimum 1s) {
  <p>Loading…</p>
} @error {
  <p>Could not load this content.</p>
}

Without a trigger, the main block loads when the browser becomes idle. That is the default, so a bare @defer does not load immediately after the parent template renders.

Which components can be deferred

Deferral only changes bundling for dependencies that meet every eligibility rule. If one of these rules fails, the code stays in the eager bundle and the block gains no benefit:

  • Each component, directive, and pipe used only inside the block must be standalone.
  • None of them may also be referenced outside the @defer block in the same file.
  • None of them may be targeted by a ViewChild query.
  • Transitive dependencies (the things those components import) do not all need to be standalone.

When a component is used in two places in one file, the eager reference keeps it in the main bundle. Moving the eager usage to a separate component file is the usual fix.

Triggers: when the main content loads

Triggers are declared with on. Several triggers in one block act as an OR: the first one to fire loads the content. A when expression supplies a custom condition in your own component code.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
Trigger Syntax Loads when
Idle (default) @defer (on idle) or @defer The browser reports idle time.
Viewport @defer (on viewport) The placeholder enters the visible area.
Interaction @defer (on interaction) The user clicks, taps, or presses a key on the placeholder.
Hover @defer (on hover) The pointer moves over the placeholder.
Immediate @defer (on immediate) Right after the non-deferred content has rendered.
Timer @defer (on timer(2s)) The specified delay has elapsed.
Custom condition @defer (when isReady) The bound expression becomes true.

Choose the trigger by the user’s flow. Viewport suits content that sits below the fold and is expected to scroll into view. Interaction suits a panel the user opens on demand. Hover suits a preview that should appear only for pointer users. Timer suits a delay you can justify. Use when when readiness depends on application state, such as a feature flag or a data load your component tracks.

A when condition is one-way. After it has caused the block to load, the block does not return to its placeholder if the expression later becomes false.

Prefetching: fetch early, render later

Prefetch conditions control when the code is downloaded, not when the block is displayed. Pair a prefetch with a later display trigger to hide the download time behind the user’s next action:

@defer (on interaction; prefetch on idle) {
  <checkout-summary />
}

In this example the browser fetches the dependencies when idle, and the panel appears only after the user interacts with the placeholder. Prefetching with prefetch when works the same way, using a custom condition. Prefetching adds network work earlier, so it helps most where the user is likely to need the content and the idle time is otherwise unused.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Placeholder, loading, and error blocks

The @placeholder, @loading, and @error blocks are eagerly loaded. Their own dependencies are included in the initial bundle, so keep them light. Use them to reserve space and communicate state:

  • Placeholder shows before the trigger fires. Give it the same approximate dimensions as the real content.
  • Loading shows while dependencies are fetched. The after option delays it, so fast loads never flash the spinner. The minimum option keeps it visible long enough to avoid a flicker when the load finishes just after after expires.
  • Error shows when the dependency fetch fails, which is the place for a retry message or fallback.

In the basic example, after 100ms means the loading content waits 100 milliseconds, and minimum 1s keeps it on screen for at least one second once it appears.

Server-side rendering and hydration

By default, server-side rendering (SSR) and static site generation (SSG) render the placeholder, or nothing when no placeholder is defined. Defer triggers do not run on the server. The content therefore appears on the client after the trigger fires, which may be a noticeable delay for users who depend on the server-rendered HTML.

Incremental Hydration changes this. With it, hydrate triggers can load a deferred block’s dependencies during server rendering, so the main template is rendered on the server and then hydrated according to the configured trigger. The Incremental Hydration guide covers the setup. If your app does not use it, plan for placeholder-first output on the server.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.Support on Ko-Fi

Accessibility and layout shift

Two risks deserve attention before you adopt deferral widely.

  • Visible initial content. Angular advises against deferring content that appears in the initial viewport. When a placeholder with different dimensions is swapped for the real content, the page can shift, which may increase cumulative layout shift (CLS). Keep placeholders the same size, or do not defer content the user sees at first load.
  • Screen readers. Assistive technology may encounter only placeholder or loading content and may not announce the change to the loaded content. The Angular guide demonstrates wrapping the block in a live region so state changes are announced:
<div aria-live="polite">
  @defer (on viewport) {
    <product-reviews />
  } @placeholder {
    <p>Reviews will load as you scroll.</p>
  } @loading {
    <p>Loading reviews…</p>
  }
</div>

Test the result with a screen reader on the actual page, not only in the development server.

Nested blocks

When a deferred block contains another deferred block with the same trigger, both can fire together, causing concurrent requests that cascade into each other. Give nested blocks different triggers, for example an outer on viewport and an inner on interaction, so each request happens at a distinct moment.

A practical adoption checklist

  • Confirm the content is not needed for first render or the first screen.
  • Check that every dependency is standalone and used only inside the block.
  • Choose a trigger that matches the user action that reveals the content.
  • Add a prefetch only when the early download is likely to be used.
  • Size the placeholder to the final content and keep placeholder dependencies small.
  • Wrap state changes in a live region for assistive technology users.
  • Verify the actual bundle output and the layout on a production build.

”

The Bottom Line

Use @defer for content that is genuinely secondary to first render: below-the-fold sections, panels opened on demand, and optional widgets. Keep first-screen content eager, make placeholders match their final size, and wrap state changes so screen-reader users hear them. Confirm the bundle and layout effect on your own production build rather than assuming a gain.

Free tools Windows power users keep installed

One-click scans. No signup required.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.