@defer in Angular: Lazy Rendering for Better Performance

Posted on 2025-06-14 by Burak Hamdi TUFAN
Web
@defer in Angular: Lazy Rendering for Better Performance
Hello everyone, in this article we are going to talk about lazy rendering with @defer in angular for better performance of the Angular web applications with the help of examples.

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.

It helps with:
  • Reducing Time to Interactive
  • Lowering initial bundle size to download
  • Improving Core Web Vitals
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:

  • idle Triggers when the browser is idle.
  • viewport Triggers when specified content enters the viewport
  • interaction Triggers when the user interacts with specified element
  • hover Triggers when the mouse hovers over specified area
  • immediate Triggers immediately after non-deferred content has finished rendering
  • timer Triggers after a specific duration
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


Tags
Share this Post
Send with Whatsapp