Back

Mise en cache intelligente dans Next.js : Rendu partiel et composants réutilisables

Mise en cache intelligente dans Next.js : Rendu partiel et composants réutilisables

Vous avez créé une application Next.js avec App Router. Les récupérations de données fonctionnent. Les pages s’affichent. Mais vous n’êtes pas certain que votre stratégie de mise en cache soit correcte—ou même que vous en ayez une. Vous avez vu des données obsolètes apparaître de manière inattendue, observé la même requête de base de données se déclencher plusieurs fois par requête, et vous êtes demandé pourquoi certaines routes semblent lentes malgré leur caractère « statique ».

Cet article explique comment fonctionne réellement la mise en cache des données dans Next.js App Router, comment les trois couches de cache interagissent, et comment construire des composants serveur réutilisables qui encapsulent à la fois la récupération de données et la politique de mise en cache. Nous aborderons également le Partial Prerendering de Next.js et comment le rendu partiel de React 19 permet des stratégies de mise en cache au niveau des composants.

Points clés à retenir

  • Next.js utilise trois couches de cache (Data Cache, Full Route Cache, Router Cache) qui s’enchaînent lors des requêtes
  • Les composants doivent gérer leur propre politique de mise en cache en utilisant cache() de React pour la déduplication et les options fetch pour le contrôle de durée de vie
  • La revalidation basée sur les tags permet une invalidation chirurgicale du cache sur plusieurs routes
  • Le Partial Prerendering (PPR) permet de mélanger des shells statiques avec du contenu dynamique en streaming via les limites Suspense

Comment les trois couches de cache fonctionnent ensemble

La mise en cache de Next.js fonctionne à travers trois mécanismes distincts qui interagissent lors de chaque requête.

Data Cache (Cache de données)

Le Data Cache persiste les résultats de fetch entre les requêtes et les déploiements. Lorsque vous appelez fetch avec la mise en cache activée, Next.js stocke la réponse côté serveur. Les requêtes suivantes renvoient les données en cache jusqu’à ce qu’une revalidation se produise.

// Mis en cache pendant 1 heure pour toutes les requêtes
const posts = await fetch('https://api.example.com/posts', {
  next: { revalidate: 3600 }
})

Full Route Cache (Cache de route complet)

Au moment du build, Next.js rend les routes statiques en HTML et en payloads RSC. Ce Full Route Cache sert le contenu pré-rendu instantanément. Les routes purement dynamiques contournent ce cache, mais les routes avec des segments statiques ou une revalidation peuvent toujours générer des shells statiques.

Router Cache côté client

Le navigateur stocke les payloads RSC en mémoire pendant la navigation. Les layouts persistent lors des changements de route. Les routes visitées sont mises en cache en mémoire pour la session et réutilisées pendant la navigation jusqu’à invalidation.

Ces couches s’enchaînent : l’invalidation du Data Cache affecte les requêtes suivantes, et le Full Route Cache ou le Router Cache se mettent à jour lors du prochain rendu nécessitant des données fraîches.

Construire des composants serveur réutilisables avec cache

Le modèle mental qui prévient les bugs de données obsolètes : les composants doivent gérer leur propre politique de mise en cache.

// lib/data.ts
import { cache } from 'react'

export const getProduct = cache(async (id: string) => {
  const res = await fetch(`https://api.example.com/products/${id}`, {
    next: { revalidate: 300, tags: ['products', `product-${id}`] }
  })
  return res.json()
})

Cette fonction peut être appelée depuis n’importe quel composant—layout, page ou enfant imbriqué. Le cache() de React déduplique les appels au sein d’un seul cycle de rendu. L’option next.revalidate contrôle la durée de vie du Data Cache. Les tags permettent une invalidation chirurgicale.

Utilisez cette fonction n’importe où sans prop drilling :

// app/products/[id]/page.tsx
export default async function ProductPage({ params }: { params: { id: string } }) {
  const { id } = await params
  const product = await getProduct(id)
  return <ProductDetails product={product} />
}

Façonner le comportement du cache avec les options de segment de route

Au-delà des options fetch, les configurations de segment de route contrôlent la mise en cache au niveau de la route :

// Forcer le rendu dynamique
export const dynamic = 'force-dynamic'

// Définir la période de revalidation pour tous les fetch
export const revalidate = 3600

Pour une invalidation à la demande, utilisez revalidatePath ou la revalidation basée sur les tags :

// app/actions.ts
'use server'
import { revalidateTag } from 'next/cache'

export async function updateProduct(id: string) {
  // await db.product.update(...)
  revalidateTag(`product-${id}`)
}

Partial Prerendering de Next.js : La direction expérimentale

Le Partial Prerendering de Next.js représente un changement significatif. Au lieu de choisir entre des routes entièrement statiques ou entièrement dynamiques, le PPR pré-rend un shell statique tout en diffusant du contenu dynamique via les limites Suspense.

import { Suspense } from 'react'

export default async function ProductPage({ params }: { params: { id: string } }) {
  const { id } = await params
  
  return (
    <>
      {/* Shell statique - pré-rendu */}
      <Header />
      <ProductInfo id={id} />
      
      {/* Zone dynamique - diffusée au moment de la requête */}
      <Suspense fallback={<CartSkeleton />}>
        <UserCart />
      </Suspense>
    </>
  )
}

Les portions statiques sont servies instantanément. Les sections dynamiques sont diffusées au fur et à mesure qu’elles se résolvent. Cette fonctionnalité est encore expérimentale—activez-la via ppr: true dans les options expérimentales de votre next.config.js—mais elle indique l’avenir de la mise en cache Next.js.

React 19 et mise en cache au niveau des composants

Le comportement amélioré de Suspense dans React 19 permet des stratégies de mise en cache plus granulaires. Les composants enveloppés dans Suspense peuvent gérer indépendamment leur cycle de vie de données. En utilisant les API expérimentales use cache et cacheLife, vous pouvez mettre en cache des sous-arbres de composants plutôt que des pages entières :

import { cacheLife } from 'next/cache'

async function BlogPosts() {
  'use cache'
  cacheLife('hours')
  
  const res = await fetch('https://api.example.com/posts')
  const posts = await res.json()
  return <PostList posts={posts} />
}

La revalidation basée sur les tags permet aux équipes de partager des données en cache en toute sécurité entre les routes. Un composant produit utilisé à la fois dans /products/[id] et /checkout peut être invalidé une seule fois, se mettant à jour partout.

Conclusion

Construisez des composants serveur qui encapsulent leur politique de mise en cache. Utilisez cache() de React pour la déduplication des requêtes, les options fetch pour le contrôle du Data Cache, et les tags pour l’invalidation inter-routes. Le Partial Prerendering est expérimental mais mérite d’être compris—c’est la direction que prend la mise en cache Next.js.

L’objectif n’est pas une mise en cache maximale. C’est une mise en cache prévisible qui correspond aux véritables exigences de fraîcheur de vos données.

FAQ

Le cache() de React déduplique les appels de fonction au sein d'un seul cycle de rendu, empêchant les mêmes données d'être récupérées plusieurs fois pendant une requête. La mise en cache fetch de Next.js persiste les résultats entre plusieurs requêtes et déploiements en utilisant le Data Cache. Utilisez les deux ensemble : cache() pour la déduplication au moment du rendu et les options fetch pour la persistance inter-requêtes.

Utilisez revalidateTag lorsque vous devez invalider des données spécifiques sur plusieurs routes, comme des informations produit affichées à la fois sur les pages de détail et de paiement. Utilisez revalidatePath lorsque vous voulez invalider toutes les données en cache pour un chemin URL spécifique. Les tags offrent un contrôle plus chirurgical tandis que les chemins sont plus simples pour l'invalidation d'une seule route.

Vérifiez la sortie de votre build pour les indicateurs de route. Les routes statiques affichent une icône de cercle tandis que les routes dynamiques affichent un symbole lambda. Vous pouvez également ajouter des console.log dans vos composants—s'ils s'affichent à chaque requête, la route est dynamique. L'utilisation de cookies(), headers() ou searchParams opte automatiquement les routes pour un rendu dynamique.

Le Partial Prerendering est encore expérimental depuis Next.js 15. Bien que vous puissiez l'activer pour des tests, il n'est pas encore recommandé pour les applications de production. L'API et le comportement peuvent changer dans les versions futures. Surveillez la documentation Next.js et les notes de version pour les mises à jour de stabilité avant de l'adopter en production.

Gain Debugging Superpowers

Unleash the power of session replay to reproduce bugs, track slowdowns and uncover frustrations in your app. Get complete visibility into your frontend with OpenReplay — the most advanced open-source session replay tool for developers. Check our GitHub repo and join the thousands of developers in our community.

OpenReplay