Deferrable views, also known as @defer blocks, reduce the initial bundle size of your application by deferring the loading of code that is not strictly necessary for the initial rendering of a page. This often results in a faster initial load and improvement in Core Web Vitals (CWV), primarily Largest Contentful Paint (LCP) and Time to First Byte (TTFB).
To use this feature, you can declaratively wrap a section of your template in a @defer block:
@defer { <large-component />}
The code for any components, directives, and pipes inside the @defer block is split into a separate JavaScript file and loaded only when necessary, after the rest of the template has been rendered.
Deferrable views support a variety of triggers, prefetching options, and sub-blocks for placeholder, loading, and error state management.
Which dependencies are deferred?
Components, directives, pipes, and any component CSS styles can be deferred when loading an application.
In order for the dependencies within a @defer block to be deferred, they need to meet two conditions:
- They must be standalone. Non-standalone dependencies cannot be deferred and are still eagerly loaded, even if they are inside of
@deferblocks. - They cannot be referenced outside of
@deferblocks within the same file. If they are referenced outside the@deferblock or referenced within ViewChild queries, the dependencies will be eagerly loaded.
The transitive dependencies of the components, directives and pipes used in the @defer block do not strictly need to be standalone; transitive dependencies can still be declared in an NgModule and participate in deferred loading.
Angular's compiler produces a dynamic import statement for each component, directive, and pipe used in the @defer block. The main content of the block renders after all the imports resolve. Angular does not guarantee any particular order for these imports.
How to manage different stages of deferred loading
@defer blocks have several sub blocks to allow you to gracefully handle different stages in the deferred loading process.
@defer
This is the primary block that defines the section of content that is lazily loaded. It is not rendered initiallyβ deferred content loads and renders once the specified trigger occurs or the when condition is met.
By default, a @defer block is triggered when the browser state becomes idle.
@defer { <large-component />}
Show placeholder content with @placeholder
By default, defer blocks do not render any content before they are triggered.
The @placeholder is an optional block that declares what content to show before the @defer block is triggered.
@defer { <large-component />} @placeholder { <p>Placeholder content</p>}
While optional, certain triggers may require the presence of either a @placeholder or a template reference variable to function. See the Triggers section for more details.
Angular replaces placeholder content with the main content once loading is complete. You can use any content in the placeholder section including plain HTML, components, directives, and pipes. Keep in mind the dependencies of the placeholder block are eagerly loaded.
The @placeholder block accepts an optional parameter to specify the minimum amount of time that this placeholder should be shown after the placeholder content initially renders.
@defer { <large-component />} @placeholder (minimum 500ms) { <p>Placeholder content</p>}
This minimum parameter is specified in time increments of milliseconds (ms) or seconds (s). You can use this parameter to prevent fast flickering of placeholder content in the case that the deferred dependencies are fetched quickly.
Show loading content with @loading
The @loading block is an optional block that allows you to declare content that is shown while deferred dependencies are loading. It replaces the @placeholder block once loading is triggered.
@defer { <large-component />} @loading { <img alt="loading..." src="loading.gif" />} @placeholder { <p>Placeholder content</p>}
Its dependencies are eagerly loaded (similar to @placeholder).
The @loading block accepts two optional parameters to help prevent fast flickering of content that may occur when deferred dependencies are fetched quickly,:
minimum- the minimum amount of time that this placeholder should be shownafter- the amount of time to wait after loading begins before showing the loading template
@defer { <large-component />} @loading (after 100ms; minimum 1s) { <img alt="loading..." src="loading.gif" />}
Both parameters are specified in time increments of milliseconds (ms) or seconds (s). In addition, the timers for both parameters begin immediately after the loading has been triggered.
Show error state when deferred loading fails with @error
The @error block is an optional block that displays if deferred loading fails. Similar to @placeholder and @loading, the dependencies of the @error block are eagerly loaded.
@defer { <large-component />} @error { <p>Failed to load large component.</p>}
Controlling deferred content loading with triggers
You can specify triggers that control when Angular loads and displays deferred content.
When a @defer block is triggered, it replaces placeholder content with lazily loaded content.
Multiple event triggers can be defined by separating them with a semicolon, ; and will be evaluated as OR conditions.
There are two types of triggers: on and when.
on
on specifies a condition for when the @defer block is triggered.
The available triggers are as follows:
| Trigger | Description |
|---|---|
idle |
Triggers when the browser is idle. |