Rendu côté serveur (SSR)
Le SSR Angular pré-rend les pages côté serveur avant de les envoyer au navigateur, améliorant les performances de chargement initial et le SEO.
Ajouter le SSR
Section intitulée « Ajouter le SSR »ng add @angular/ssrFichiers générés :
src/app/app.config.server.ts— providers serveursrc/server.ts— point d’entrée Express
Configuration serveur
Section intitulée « Configuration serveur »import { mergeApplicationConfig, ApplicationConfig } from '@angular/core';import { provideServerRendering } from '@angular/platform-server';import { appConfig } from './app.config';
const serverConfig: ApplicationConfig = { providers: [provideServerRendering()],};
export const config = mergeApplicationConfig(appConfig, serverConfig);Activer l’hydratation (app.config.ts)
Section intitulée « Activer l’hydratation (app.config.ts) »import { provideClientHydration } from '@angular/platform-browser';
export const appConfig: ApplicationConfig = { providers: [ provideRouter(routes), provideHttpClient(), provideClientHydration(), // Évite les scintillements lors de l'hydratation ],};Protéger les API réservées au navigateur
Section intitulée « Protéger les API réservées au navigateur »Le serveur n’a pas accès à window, document ni localStorage. Utilisez isPlatformBrowser ou afterNextRender :
import { PLATFORM_ID, inject, afterNextRender } from '@angular/core';import { isPlatformBrowser } from '@angular/common';
export class MyComponent { private platformId = inject(PLATFORM_ID);
// Option A : isPlatformBrowser ngOnInit() { if (isPlatformBrowser(this.platformId)) { const value = localStorage.getItem('cle'); } }
// Option B : afterNextRender (recommandé, Angular 16+) constructor() { afterNextRender(() => { // S'exécute uniquement dans le navigateur après le premier rendu this.initBibliothequeExterne(); }); }}Transfert d’état (éviter le double fetch)
Section intitulée « Transfert d’état (éviter le double fetch) »Sans transfert d’état, Angular re-récupère les données dans le navigateur que le serveur avait déjà récupérées.
import { TransferState, makeStateKey, inject } from '@angular/core';import { HttpClient } from '@angular/common/http';import { of, tap } from 'rxjs';
const ALBUMS_KEY = makeStateKey<Album[]>('albums');
@Injectable({ providedIn: 'root' })export class AlbumService { private http = inject(HttpClient); private transferState = inject(TransferState);
getAlbums() { const cached = this.transferState.get(ALBUMS_KEY, null); if (cached) { this.transferState.remove(ALBUMS_KEY); return of(cached); } return this.http.get<Album[]>('/api/albums').pipe( tap(data => this.transferState.set(ALBUMS_KEY, data)) ); }}Construire et exécuter
Section intitulée « Construire et exécuter »# Construire les bundles navigateur + serveurng build
# Démarrer le serveur SSRnode dist/my-app/server/server.mjsStructure de sortie :
dist/my-app/├── browser/ ← Ressources statiques└── server/ └── server.mjs ← Serveur NodeVérifier que le SSR fonctionne
Section intitulée « Vérifier que le SSR fonctionne »- Ouvrez
http://localhost:4000 - Affichez la source de la page (Ctrl+U)
- Le HTML de la page doit contenir votre contenu rendu — et non juste
<app-root></app-root>
Erreurs courantes
Section intitulée « Erreurs courantes »| Problème | Solution |
|---|---|
window is not defined |
Protéger avec isPlatformBrowser ou afterNextRender |
| Données récupérées deux fois | Utiliser TransferState |
| Désaccord d’hydratation | S’assurer que le serveur et le client rendent le même HTML |
Crash localStorage |
Déplacer l’accès au stockage derrière une vérification de plateforme |

