Comment utiliser le Prérendu Partiel (Partial Prerendering)

Le Prérendu Partiel (PPR) est une stratégie de rendu qui vous permet de combiner du contenu statique et dynamique dans la même route. Cela améliore les performances initiales de la page tout en prenant en charge des données dynamiques et personnalisées.

Page de produit partiellement prérendue montrant une navigation statique et des informations sur le produit, ainsi qu'un panier dynamique et des produits recommandés

Lorsqu'un utilisateur visite une route :

  • Le serveur envoie une enveloppe contenant le contenu statique, garantissant un chargement initial rapide.
  • L'enveloppe laisse des trous pour le contenu dynamique qui se chargera de manière asynchrone.
  • Les trous dynamiques sont transmis en parallèle, réduisant ainsi le temps de chargement global de la page.

🎥 Regarder : Pourquoi PPR et comment ça fonctionne → YouTube (10 minutes).

Comment fonctionne le Prérendu Partiel ?

Pour comprendre le Prérendu Partiel, il est utile de connaître les stratégies de rendu disponibles dans Next.js.

Rendu Statique (Static Rendering)

Avec le Rendu Statique, le HTML est généré à l'avance—soit au moment de la construction, soit via revalidation. Le résultat est mis en cache et partagé entre les utilisateurs et les requêtes.

Dans le Prérendu Partiel, Next.js prérend une enveloppe statique pour une route. Cela peut inclure la mise en page et tout autre composant qui ne dépend pas de données au moment de la requête.

Rendu Dynamique (Dynamic Rendering)

Avec le Rendu Dynamique, le HTML est généré au moment de la requête. Cela vous permet de servir un contenu personnalisé basé sur des données au moment de la requête.

Un composant devient dynamique s'il utilise les API suivantes :

Dans le Prérendu Partiel, l'utilisation de ces API génère une erreur React spéciale qui informe Next.js que le composant ne peut pas être rendu statiquement, provoquant une erreur de construction. Vous pouvez utiliser une limite Suspense pour encapsuler votre composant et différer son rendu jusqu'au moment de l'exécution.

Suspense

React Suspense est utilisé pour différer le rendu de certaines parties de votre application jusqu'à ce qu'une condition soit remplie.

Dans le Prérendu Partiel, Suspense est utilisé pour marquer les limites dynamiques dans votre arborescence de composants.

Au moment de la construction, Next.js prérend le contenu statique et l'interface utilisateur de fallback. Le contenu dynamique est reporté jusqu'à ce que l'utilisateur demande la route.

Encapsuler un composant dans Suspense ne rend pas le composant lui-même dynamique (c'est l'utilisation de vos API qui le fait), mais Suspense est utilisé comme une limite qui encapsule le contenu dynamique et permet le streaming.

app/page.js
import { Suspense } from 'react'
import StaticComponent from './StaticComponent'
import DynamicComponent from './DynamicComponent'
import Fallback from './Fallback'

export const experimental_ppr = true

export default function Page() {
  return (
    <>
      <StaticComponent />
      <Suspense fallback={<Fallback />}>
        <DynamicComponent />
      </Suspense>
    </>
  )
}

Streaming

Le Streaming divise la route en morceaux et les transmet progressivement au client dès qu'ils sont prêts. Cela permet à l'utilisateur de voir certaines parties de la page immédiatement, avant que tout le contenu n'ait fini de se rendre.

Diagramme montrant une page partiellement rendue côté client, avec une interface de chargement pour les morceaux en cours de streaming.

Dans le Prérendu Partiel, les composants dynamiques encapsulés dans Suspense commencent à être transmis depuis le serveur en parallèle.

Diagramme montrant la parallélisation des segments de route pendant le streaming, montrant la récupération des données, le rendu et l'hydratation des morceaux individuels.

Pour réduire la surcharge réseau, la réponse complète—y compris le HTML statique et les parties dynamiques transmises—est envoyée dans une seule requête HTTP. Cela évite des allers-retours supplémentaires et améliore à la fois le chargement initial et les performances globales.

Activation du Prérendu Partiel

Vous pouvez activer PPR en ajoutant l'option ppr à votre fichier next.config.ts :

import type { NextConfig } from 'next'

const nextConfig: NextConfig = {
  experimental: {
    ppr: 'incremental',
  },
}

export default nextConfig

La valeur 'incremental' vous permet d'adopter PPR pour des routes spécifiques :

/app/dashboard/layout.tsx
export const experimental_ppr = true

export default function Layout({ children }: { children: React.ReactNode }) {
  // ...
}
/app/dashboard/layout.js
export const experimental_ppr = true

export default function Layout({ children }) {
  // ...
}

Les routes qui n'ont pas experimental_ppr auront par défaut la valeur false et ne seront pas prérendues avec PPR. Vous devez explicitement activer PPR pour chaque route.

Bon à savoir :

  • experimental_ppr s'appliquera à tous les enfants du segment de route, y compris les mises en page et les pages imbriquées. Vous n'avez pas besoin de l'ajouter à chaque fichier, seulement au segment supérieur d'une route.
  • Pour désactiver PPR pour les segments enfants, vous pouvez définir experimental_ppr sur false dans le segment enfant.

Exemples

API Dynamiques

Lors de l'utilisation d'API dynamiques qui nécessitent d'examiner la requête entrante, Next.js passera en mode rendu dynamique pour la route. Pour continuer à utiliser PPR, encapsulez le composant avec Suspense. Par exemple, le composant <User /> est dynamique car il utilise l'API cookies :

import { cookies } from 'next/headers'

export async function User() {
  const session = (await cookies()).get('session')?.value
  return '...'
}

Le composant <User /> sera transmis en streaming tandis que tout autre contenu à l'intérieur de <Page /> sera prérendu et fera partie de l'enveloppe statique.

import { Suspense } from 'react'
import { User, AvatarSkeleton } from './user'

export const experimental_ppr = true

export default function Page() {
  return (
    <section>
      <h1>Ceci sera prérendu</h1>
      <Suspense fallback={<AvatarSkeleton />}>
        <User />
      </Suspense>
    </section>
  )
}

Passage de props dynamiques

Les composants ne passent en mode rendu dynamique que lorsque la valeur est accédée. Par exemple, si vous lisez searchParams depuis un composant <Page />, vous pouvez transmettre cette valeur à un autre composant en tant que prop :

import { Table, TableSkeleton } from './table'
import { Suspense } from 'react'

export default function Page({
  searchParams,
}: {
  searchParams: Promise<{ sort: string }>
}) {
  return (
    <section>
      <h1>Ceci sera prérendu</h1>
      <Suspense fallback={<TableSkeleton />}>
        <Table searchParams={searchParams} />
      </Suspense>
    </section>
  )
}

À l'intérieur du composant Table, l'accès à la valeur de searchParams rendra le composant dynamique tandis que le reste de la page sera prérendu.

export async function Table({
  searchParams,
}: {
  searchParams: Promise<{ sort: string }>
}) {
  const sort = (await searchParams).sort === 'true'
  return '...'
}

On this page