DEV Community

Giorgio Galassi
Giorgio Galassi

Posted on

Angular v19+ — Understanding @defer: Blocks, Triggers, and Deferrable Views (Part 2) 🔥🚀

One of the main goals in modern Angular apps is reducing hydration costs and improving user experience. With Angular v19, we finally get native tools to achieve this: Incremental Hydration and Event Replay.

In Part 1, we explored the fundamentals of @defer blocks and triggers. Now, let’s see how Angular extends that foundation to make hydration smarter and interactions smoother.


💧 Incremental Hydration

Hydration is the process of transforming a pre-rendered HTML page (generated by server-side rendering) into a fully interactive Angular app on the client side.

Incremental Hydration takes this a step further by letting you control when specific parts of your application should become interactive.

This means better Core Web Vitals, faster initial paints, and a smoother user experience overall.

Activate it like this:

export const appConfig: ApplicationConfig = {
  providers: [
    // other providers
    provideClientHydration(withIncrementalHydration())
  ]
};
Enter fullscreen mode Exit fullscreen mode

Once configured, you can start deferring hydration for parts of your UI:

@defer (hydrate on idle) {
  <large-cmp />
} @placeholder {
  <div>Large component placeholder</div>
}
Enter fullscreen mode Exit fullscreen mode

The hydrate syntax mirrors the classic @defer structure, supporting the same triggers and patterns. You can even combine behaviors:

@defer (on idle; hydrate on interaction) {
  <large-cmp />
} @placeholder {
  <div>Example Placeholder</div>
}
Enter fullscreen mode Exit fullscreen mode

Note: The on interaction trigger behaves differently when used with hydrate. Classic @defer requires an element reference, while hydrate doesn’t—the interaction happens directly with the de-hydrated version of the component.

Example:

<!-- Classic @defer -->
<div #greeting>Hello!</div>

@defer (on interaction(greeting)) {
  <greetings-cmp />
}

<!-- @defer with hydrate -->
@defer (hydrate on interaction) {
  <greetings-cmp />
}
Enter fullscreen mode Exit fullscreen mode

With hydrate, the component itself is the trigger, simplifying setup and making it easier to use in real-world hydration scenarios.

Why it matters

Incremental Hydration is especially valuable for large apps with multiple deferred views — dashboards, content-heavy pages, or e-commerce layouts. It helps you decide when to activate interactivity, improving both performance and responsiveness.


⚡ Event Replay

Server-Side Rendering (SSR) is key for performance and SEO, but it introduces a common problem: lost interactions.

When HTML is pre-rendered, users can start clicking before the JavaScript is fully hydrated. Without proper handling, those interactions are lost — leading to broken UX.

Event Replay fixes this by capturing events during hydration and replaying them in the same order they occurred.

This ensures every user action is processed, even if it happened before the app became interactive.

Activate it with:

export const appConfig: ApplicationConfig = {
  providers: [
    // other providers
    provideClientHydration(withEventReplay())
  ]
};
Enter fullscreen mode Exit fullscreen mode

If you’re already using withIncrementalHydration(), you don’t need to add withEventReplay() separately—it’s included automatically.

Why it matters

Event Replay ensures that no user action is lost. It captures input events (like clicks, scrolls, or typing) and replays them after hydration. The result is a seamless, frustration-free experience for users.


🧩 Combined Example

Here’s how both features can work together:

export const appConfig: ApplicationConfig = {
  providers: [
    provideClientHydration(withIncrementalHydration())
  ]
};
Enter fullscreen mode Exit fullscreen mode
@defer (hydrate on interaction) {
  <user-profile />
} @placeholder {
  <loading-spinner />
}
Enter fullscreen mode Exit fullscreen mode

In this example, Angular hydrates the user-profile component only after the user interacts with its placeholder. Any clicks made before hydration are safely replayed, thanks to Event Replay.


🧠 Behind the Scenes

Under the hood:

  • Incremental Hydration reuses the server-generated DOM and attaches event listeners lazily.
  • Event Replay hooks into the browser’s event queue, caching early interactions and re-dispatching them once hydration is complete.

These optimizations work together to provide a faster, more resilient user experience especially in apps with complex, interactive UIs.


🪄 Key Takeaways

  • Incremental Hydration lets you decide when to make parts of your app interactive.
  • Event Replay ensures no interaction is lost during hydration.
  • Combined, they improve Core Web Vitals, reduce Time to Interactive, and simplify performance optimization in Angular.
  • 👉 Try it live on StackBlitz to see Incremental Hydration and Event Replay in action! Core Web Vitals, reduce Time to Interactive, and simplify performance optimization in Angular.

If you found this helpful, follow me here and on LinkedIn for more deep dives into Angular, web performance, and modern frontend development.

See you in the next one! 🤙🏻
— G.

Top comments (0)