Telerik blogs

Take a closer look at the new hydration in Angular and how you can get rid of the dreaded flicker in your SSR Angular apps.

It has finally arrived. The dreaded flicker in Angular Universal is gone!

Angular 17 comes with a lot of nifty new features, proving that the team listens to its users. With all the advancements in other frameworks, it is good to know that new Angular 17 has made strives in Server-Side Rendering (SSR) as well.

Universal

Angular Universal is gone, and now we have SSR. Instead of adding a new package, the default Angular installation has an option to install @angular/ssr, which is its replacement. The default is also now standalone components.

Flicker

One of the most prominent issues has been the “dreaded flicker.” This is due to “Angular having destroyed and repainted the DOM structures after re-bootstrapping on the client.” Since Angular 16, the Angular Team as redesigned the entire hydration system, greatly enhancing the process to solve the problem.

Non-Destructive Hydration

Before this was present, Angular would send the HTML for the client to immediately load. The code would get created on the server dynamically. However, once the data was loaded to the DOM, it got destroyed. With the new method of “non-destructive hydration,” Angular can reuse these DOM elements, instead of destroying them and recreating them.

Core Web Vitals

When the page loads and reloads, this can affect the Core Web Vitals statistics, or the way the webpage’s loading performance is measured. This is important for SEO rankings. This has directly improved the numbers for these measurements:

Installing Server-Side Rendering

When you first create a project with Angular 17 by using ng new, you will get a few options. Make sure to select y to Server-Side Rendering.

ng new test asks which stylesheet format; user has CSS. Do you want to enable Server-Side Rendering (SSR) and Static Site Generation (SSG/Prerendering)? y

This will automatically add the hydration provider to your app.config.ts file:

import { ApplicationConfig } from '@angular/core';
import { provideRouter } from '@angular/router';

import { routes } from './app.routes';
import { provideClientHydration } from '@angular/platform-browser';

export const appConfig: ApplicationConfig = {
  providers: [provideRouter(routes), provideClientHydration()]
};

Alternatively, you could add the provideClientHydration manually to an existing project or to an app module:

import {provideClientHydration} from '@angular/platform-browser';
import {NgModule} from '@angular/core';

@NgModule({
  declarations: [RootCmp],
  exports: [RootCmp],
  bootstrap: [RootCmp],
  providers: [provideClientHydration()],
})
export class AppModule {}

Caveats

  • Server-rendered HTML must exactly match the client rendered HTML.
  • No direct DOM manipulation with innerHTML, outerHTML, etc. Use Angular functions.
  • You must have Valid HTML.
  • Zoneless noop ZoneJS is not supported … yet!

Testing

You can remove the provideClientHydration provider to test Angular without it. You can also see how it works in dev mode by viewing the console in Developer Tools.

Angular is running in development mode. Angular hydrated 1 component and 66 nodes, 0 components were skipped.

Angular has come a LONG way. Angular 16 brought signals, Angular 17 brought more speed enhancements and syntax, and Angular 18 will hopefully default to NoopZone for even faster applications without ZoneJS.

Angular is a beast.


About the Author

Jonathan Gamble

Jonathan Gamble has been an avid web programmer for more than 20 years. He has been building web applications as a hobby since he was 16 years old, and he received a post-bachelor’s in Computer Science from Oregon State. His real passions are language learning and playing rock piano, but he never gets away from coding. Read more from him at https://code.build/.

 

 

Related Posts

Comments

Comments are disabled in preview mode.