@defer in Angular: Lazy Rendering for Better Performance
Lets get started.
Angular has long been a powerful framework for building dynamic, single-page applications. With the release of Angular 17, a new set of control flow constructs was introduced to modernize templates. Among them, @defer is a game-changer for performance optimization via deferred (lazy) rendering.
What is @defer?
@defer is a directive-like control flow syntax that allows Angular to delay rendering part of the template until a certain condition or trigger is met. This is useful when rendering parts of the UI that are expensive to compute, not immediately visible, or not needed at initial load.
Here is syntax of lazy loading
@defer (when: condition) {
<!-- Deferred block -->
} @placeholder {
<!-- Placeholder while loading -->
} @loading {
<!-- Optional loading state -->
} @error {
<!-- Optional error fallback -->
} @complete {
<!-- Optional completion block -->
}
In here we can define multiple states of the loading. Here only @defer body is required and the @placeholder, @loading, @error and @complete are optional.
Now lets make an example about component deferring in Angular
Here is the lazy loading component definition in the template file.
app.component.html
@defer (when: showAnalytics) {
<app-analytics></app-analytics>
} @placeholder {
<p>Analytics will load soon...</p>
}
Here is the lazy loading component definition in the component file to simlate the deferring the componen.
app.component.ts
export class AppComponent {
showAnalytics = false;
ngOnInit() {
setTimeout(() => {
this.showAnalytics = true;
}, 3000); // simulate user delay
}
}
So above the app will wait 3 seconds before loading and rendering app-analytics component.
We can also use @defer with triggers with on keyword. Here is the list of the triggers:
Here is the syntax for using with triggers:
@defer (on trigger) {
<heavy-widget></heavy-widget>
}
Here are some examples of using triggers
@defer (on idle) {
<lazy-section></lazy-section>
}
@defer (on viewport) {
<lazy-section></lazy-section>
}
Pay attention with testing phases: When unit testing, ensure you wait for triggers (like when, on idle, or on viewport) before asserting DOM content.
Here is an example for testing
it('should render deferred component', fakeAsync(() => {
component.showAnalytics = true;
fixture.detectChanges();
tick();
expect(fixture.nativeElement.querySelector('app-analytics')).toBeTruthy();
}));
Summary
@defer is a powerful way to improve the performance for page loading. If you need to build data-heavy dashboards or long-form content pages, @defer helps you optimize what matters most — speed and interactivity.
By adopting deferred rendering wisely, you can significantly improve your app’s UX and performance without sacrificing maintainability.
That is all for this article.
Happy deferring
Burak Hamdi TUFAN