Ce que Next.js vous offre par défaut

  • Cache de données – Dans Next.js 13+, chaque appel fetch() atterrit dans un cache mémoire par requête. L'ajout d'une option revalidate indique au runtime de rafraîchir les données après un intervalle défini, transformant un appel API « chaud » en un appel « froid » uniquement lorsque cela est nécessaire.
  • Cache de route complète – Le framework persiste le HTML rendu et les données nécessaires à une route entière. Les visiteurs récurrents bénéficient d'une transition instantanée car le serveur saute l'étape du rendu.
  • ISR – Les pages statiques se régénèrent en arrière-plan pendant que l'ancienne version continue de servir le trafic. Cela vous permet de maintenir un site volumineux en mode statique sans reconstruction complète à chaque changement de contenu.
  • Le cache() des Server Components – L'utilitaire cache de React mémorise les calculs coûteux ou les connexions à la base de données pour la durée d'une seule requête, évitant ainsi les doublons dans l'arbre des composants d'une page.

Ces caches résolvent le problème du « premier accès », mais résident toujours à l'intérieur du processus Node. Pour protéger le serveur et la base de données, poussez la mise en cache vers l'extérieur.

Couches externes que vous pouvez ajouter

Couche Ce qu'il stocke Outil typique Comment il aide
CDN Assets statiques, HTML, JSON d'API Cloudflare, Akamai, AWS CloudFront Déplace le contenu vers des emplacements edge, réduisant le temps d'aller-retour vers l'utilisateur
Proxy inverse Réponses de pages entières avant qu'elles n'atteignent Node Nginx, Varnish Sert directement les pages mises en cache, réduisant la charge sur l'instance Next.js
Cache au niveau de l'application Résultats de requêtes DB ou d'appels API coûteux Redis, Memcached Fournit un magasin clé-valeur rapide qui survit aux redémarrages du serveur et peut être partagé entre plusieurs instances de l'application

Chaque couche se situe plus loin de la base de données d'origine ; un échec (miss) à un niveau se répercute au suivant, n'atteignant la base de données que lorsque cela est absolument nécessaire.

Maintenir la fraîcheur des caches

L'invalidation est le piège dans lequel tombent la plupart des équipes. Trois modèles pratiques fonctionnent bien :

  • Basé sur le temps (TTL) – Attribuez une expiration fixe à une entrée de cache. Simple à configurer, mais peut servir des données obsolètes jusqu'à l'expiration du minuteur.
  • Piloté par les événements – Connectez-vous à votre CMS ou à toute source de données qui émet un webhook lors d'un changement de contenu. Le webhook déclenche une purge de l'entrée de cache correspondante.
  • Basé sur les tags – Attachez un tag logique à un groupe de fetchs (ex: product-list). Lorsque n'importe quel élément de ce groupe change, un seul appel à revalidateTag('product-list') efface toutes les entrées partageant ce tag.

Mélanger ces approches vous permet d'équilibrer la fraîcheur des données et le taux de réussite du cache (cache-hit rate).

La hiérarchie qui convient à la plupart des équipes

  1. Cache du navigateur – Les assets statiques (CSS, JS, images) reçoivent un max-age élevé afin que l'appareil de l'utilisateur ne sollicite plus jamais le réseau.
  2. CDN – Les nœuds edge mettent en cache les pages HTML complètes et le JSON de l'API, en respectant les en-têtes Cache-Control que vous définissez dans Next.js.
  3. Proxy inverse – Une instance Nginx ou Varnish se place devant le serveur Next.js, servant des réponses mises en cache pour les routes qui changent rarement.
  4. Cache interne de Next.js – Les caches de données et de routes du framework gèrent la mémorisation par requête et l'ISR.
  5. Cache applicatif – Redis stocke les résultats des requêtes de base de données lourdes, indexés par paramètres de requête ou par tags.
  6. Base de données – La source de vérité ultime, interrogée uniquement en cas d'échec de cache à tous les niveaux supérieurs.

Lorsqu'une requête arrive, elle parcourt cette liste jusqu'à ce qu'une couche y réponde. La réponse la plus rapide l'emporte, et la réponse remonte la chaîne pour les futurs accès.

Mettre les éléments en place

  1. Définissez les en-têtes Cache-Control dans vos routes d'API
  2. Configurez votre CDN – Activez la mise en cache en périphérie (edge) pour les points de terminaison HTML et JSON, et assurez-vous que le CDN respecte le Cache-Control.
  3. Déployez un proxy inverse – Placez Nginx devant votre serveur Next.js.
  4. Ajoutez Redis – Mettez en cache les résultats des requêtes de base de données coûteuses.
  5. Utilisez revalidateTag dans vos composants – Appelez revalidateTag pour vider le cache interne de Next.js pour un tag spécifique.

À retenir

Un cache unique à l'intérieur de Next.js accélère la première requête, mais la véritable scalabilité provient d'une pile disciplinée : navigateur → CDN → proxy inverse → framework → Redis → base de données. Configurez chaque couche, gérez l'invalidation par le temps, les événements et les tags, et surveillez vos métriques. La latence reste faible tandis que votre backend survit aux pics de trafic.