Hydration in Angular
When you use Server-Side Rendering (SSR), the server sends a fully printed, but static, HTML page to your browser. Hydration is the process where Angular arrives, looks at the static HTML, and quickly attaches all the dynamic behavior — like buttons, form fields, and animations — to it, without throwing away the beautiful static page.
In short:
- Without hydration: The server sends a static page. Angular then downloads, deletes the static content, and rebuilds everything from scratch on the client to make it interactive.
- With hydration: The server sends a static page. Angular downloads, notices the static content is already there, and simply reuses it, adding only the necessary interactive behavior.
Example code with hydration
To use hydration, you first need to have an Angular application set up with Server-Side Rendering (SSR). If you create a new Angular project with the --ssr flag, hydration is enabled automatically.
Enable hydration in your main configuration
In your app.config.ts, you provide the client hydration feature.
// src/app/app.config.ts
import { ApplicationConfig } from '@angular/core';
import { provideClientHydration } from '@angular/platform-browser';
import { provideRouter } from '@angular/router';
import { routes } from './app.routes';
export const appConfig: ApplicationConfig = {
providers: [
provideRouter(routes),
// This is the line that enables hydration.
provideClientHydration()
]
};Create an interactive component
Here is a simple button component that needs to be interactive.
// src/app/counter-button/counter-button.component.ts
import { Component, signal } from '@angular/core';
@Component({
selector: 'app-counter-button',
standalone: true,
template: `
<button (click)="increment()">
Click count: {{ count() }}
</button>
`,
styles: `button { padding: 10px; font-size: 16px; }`
})
export class CounterButtonComponent {
count = signal(0);
increment() {
this.count.update(value => value + 1);
}
}Use the component in your app
Get Rajkamal MM’s stories in your inbox
Join Medium for free to get updates from this writer.
When you build your app for SSR, the <app-counter-button> HTML is pre-rendered on the server. When the page loads in the browser, hydration makes the button clickable without rebuilding it.
<!-- src/app/app.component.html -->
<h1>Welcome to my Hydrated App!</h1>
<p>This button becomes interactive instantly, without flashing.</p>
<app-counter-button />What happens if we don’t use hydration?
If you don’t use hydration (or, more accurately, if you skip it for a specific component), Angular behaves like older SSR applications. The process is:
- Fast static display: The server sends the HTML, and the user sees the content immediately.
- Destruction and rebuilding: Angular’s JavaScript arrives, removes the server-rendered DOM (the button from the server), and then builds a brand-new one from scratch.
- Visible flicker: The user may see a brief flicker as the button disappears and reappears, which provides a poor user experience.
- Lost interactions: If the user clicks the button before it’s re-rendered by the client, the click won’t register.
Example code without hydration
You can intentionally skip hydration for a component by using the ngSkipHydration host binding.
1. Update the interactive component
Add the host: { ngSkipHydration: 'true' } property to your component's decorator.
// src/app/counter-button/counter-button.component.ts
import { Component, signal } from '@angular/core';
@Component({
selector: 'app-counter-button',
standalone: true,
// This tells Angular to skip hydration for this component.
host: { 'ngSkipHydration': 'true' },
template: `
<button (click)="increment()">
Click count: {{ count() }}
</button>
`,
styles: `button { padding: 10px; font-size: 16px; }`
})
export class CounterButtonComponent {
count = signal(0);
increment() {
this.count.update(value => value + 1);
}
}The app’s behavior
Even though the server-side rendering will still output the HTML for the button, the ngSkipHydration flag ensures that the client-side Angular code will not reuse it. Instead, it will remove it and insert a new version, causing a visible delay and a flash of unstyled content.
Reference: https://angular.dev/guide/hydration






