Cours Next.js · Module 9: Intégrations et fonctions avancées

use cache - Une nouvelle ère du caching dans Next.js 16

7 min de lecture
Dans cette leçon7

Dans les salles serveurs de la Métropole Quantum 2150, où chaque milliseconde compte, tu vas découvrir l'API de caching révolutionnaire, apparue à titre expérimental dans Next.js 15 et devenue une partie des Cache Components dans Next.js 16. La directive use cache remplace unstable_cache (obsolète) et offre une façon bien plus intuitive de gérer le cache.

Qu'est-ce que la directive use cache ?

use cache est une nouvelle directive (semblable à use server ou use client) qui marque des fonctions ou des fichiers entiers comme cachables. Next.js gère automatiquement le cycle de vie du cache et la revalidation.

Activer les Cache Components

Pour utiliser use cache, tu dois d'abord activer l'option cacheComponents dans ta configuration :

1// next.config.js
2module.exports = {
3  cacheComponents: true,
4};

Dans Next.js 15 (dans les versions canary), la même fonctionnalité se cachait derrière les flags expérimentaux experimental.dynamicIO et experimental.useCache. Next.js 16 a supprimé ces deux flags, et cacheComponents n'est pas qu'un nouveau nom : cette option active tout le modèle Cache Components, qui peut faire apparaître des erreurs de build lorsqu'une route lit des données non mises en cache en dehors d'une limite <Suspense>.

Utilisation de base de use cache

Mettre en cache une seule fonction

1// app/lib/data.ts
2async function getProducts() {
3  'use cache';
4
5  const response = await fetch('https://api.quantum-store.com/products');
6  return response.json();
7}

Mettre en cache un fichier entier

1// app/lib/cached-data.ts
2'use cache';
3
4export async function getUsers() {
5  const response = await fetch('https://api.quantum-store.com/users');
6  return response.json();
7}
8
9export async function getOrders() {
10  const response = await fetch('https://api.quantum-store.com/orders');
11  return response.json();
12}

cacheLife - Contrôler la durée de vie du cache

La fonction cacheLife te permet de définir précisément combien de temps les données doivent rester en cache.

Profils prédéfinis

Next.js fournit des profils de temps intégrés :

1import { cacheLife } from 'next/cache';
2
3async function getNews() {
4  'use cache';
5  cacheLife('minutes'); // cache pendant quelques minutes
6
7  return fetch('https://api.quantum-news.com/latest').then(r => r.json());
8}
9
10async function getStaticContent() {
11  'use cache';
12  cacheLife('days'); // cache pendant des jours
13
14  return fetch('https://api.quantum-cms.com/static').then(r => r.json());
15}
16
17async function getRealTimeData() {
18  'use cache';
19  cacheLife('seconds'); // cache pendant quelques secondes
20
21  return fetch('https://api.quantum-sensors.com/data').then(r => r.json());
22}

Profils intégrés disponibles :

ProfilstalerevalidateexpireDescription
default5min15minjamaisLe profil utilisé quand tu n'appelles pas cacheLife
seconds30s1s60sPour des données qui changent rapidement
minutes5min1min1hPour des données mises à jour toutes les quelques minutes
hours5min1h1dPour des données horaires
days5min1d1wPour des données qui changent rarement
weeks5min1w30dPour des données quasi statiques
max5min30d1yDurée de cache maximale

Configurations cacheLife personnalisées

Tu peux définir tes propres profils dans next.config.js :

1// next.config.js
2module.exports = {
3  cacheComponents: true,
4  cacheLife: {
5    quantumFast: {
6      stale: 10,      // secondes - durée pendant laquelle les données sont « fraîches »
7      revalidate: 30, // secondes - délai après lequel revalider en arrière-plan
8      expire: 300,    // secondes - durée de vie maximale
9    },
10    quantumProducts: {
11      stale: 60,
12      revalidate: 300,
13      expire: 3600,
14    },
15  },
16};

Utiliser un profil personnalisé :

1import { cacheLife } from 'next/cache';
2
3async function getQuantumProducts() {
4  'use cache';
5  cacheLife('quantumProducts');
6
7  return fetch('https://api.quantum-store.com/products').then(r => r.json());
8}

Configuration inline

Tu peux aussi définir la configuration directement :

1import { cacheLife } from 'next/cache';
2
3async function getCriticalData() {
4  'use cache';
5  cacheLife({
6    stale: 5,
7    revalidate: 15,
8    expire: 60,
9  });
10
11  return fetch('https://api.quantum-critical.com/data').then(r => r.json());
12}

cacheTag - Tagging et revalidation sélective

cacheTag te permet d'étiqueter le cache avec des tags qui peuvent ensuite servir à une revalidation sélective.

Tagging de base

1import { cacheTag, cacheLife } from 'next/cache';
2
3async function getProduct(id: string) {
4  'use cache';
5  cacheTag(`product-${id}`);
6  cacheLife('hours');
7
8  return fetch(`https://api.quantum-store.com/products/${id}`).then(r => r.json());
9}
10
11async function getCategory(slug: string) {
12  'use cache';
13  cacheTag('categories', `category-${slug}`);
14  cacheLife('days');
15
16  return fetch(`https://api.quantum-store.com/categories/${slug}`).then(r => r.json());
17}

Revalider par tags

1// app/actions/revalidate.ts
2'use server';
3
4import { revalidateTag, updateTag } from 'next/cache';
5
6export async function updateProduct(id: string, data: ProductData) {
7  // Met à jour le produit en base de données
8  await db.products.update(id, data);
9
10  // Revalide le cache pour ce produit
11  updateTag(`product-${id}`);
12}
13
14export async function refreshAllCategories() {
15  // Revalide toutes les catégories d'un coup
16  revalidateTag('categories', 'max');
17}

Dans Next.js 16, tu as le choix entre deux fonctions. updateTag ne fonctionne que dans les Server Actions et expire le cache immédiatement : l'utilisateur voit sa modification dès la même requête. revalidateTag avec le second argument 'max' marque les données comme périmées et les rafraîchit en arrière-plan, en servant l'ancienne version entre-temps ; la forme à un seul argument est dépréciée.

Exemple pratique - Tableau de bord Quantum Store

1// app/lib/dashboard-data.ts
2import { cacheTag, cacheLife } from 'next/cache';
3
4// Données produits - cache pendant des heures, taguées
5export async function getDashboardProducts() {
6  'use cache';
7  cacheTag('dashboard', 'products');
8  cacheLife('hours');
9
10  const response = await fetch('https://api.quantum-store.com/dashboard/products');
11  return response.json();
12}
13
14// Stats de ventes - cache pendant des minutes (mises à jour fréquentes)
15export async function getSalesStats() {
16  'use cache';
17  cacheTag('dashboard', 'sales');
18  cacheLife('minutes');
19
20  const response = await fetch('https://api.quantum-store.com/dashboard/sales');
21  return response.json();
22}
23
24// Données utilisateurs - cache pendant des jours
25export async function getUserStats() {
26  'use cache';
27  cacheTag('dashboard', 'users');
28  cacheLife('days');
29
30  const response = await fetch('https://api.quantum-store.com/dashboard/users');
31  return response.json();
32}
1// app/actions/dashboard-actions.ts
2'use server';
3
4import { updateTag } from 'next/cache';
5
6export async function refreshDashboard() {
7  // Revalide tout le tableau de bord
8  updateTag('dashboard');
9}
10
11export async function refreshSalesOnly() {
12  // Revalide uniquement les ventes
13  updateTag('sales');
14}
1// app/dashboard/page.tsx
2import { getDashboardProducts, getSalesStats, getUserStats } from '@/lib/dashboard-data';
3import { refreshDashboard, refreshSalesOnly } from '@/actions/dashboard-actions';
4
5export default async function DashboardPage() {
6  const [products, sales, users] = await Promise.all([
7    getDashboardProducts(),
8    getSalesStats(),
9    getUserStats(),
10  ]);
11
12  return (
13    <div className="quantum-dashboard">
14      <header className="flex justify-between items-center">
15        <h1>Tableau de bord Quantum Store</h1>
16        <div className="flex gap-2">
17          <form action={refreshSalesOnly}>
18            <button type="submit">Rafraîchir les ventes</button>
19          </form>
20          <form action={refreshDashboard}>
21            <button type="submit">Tout rafraîchir</button>
22          </form>
23        </div>
24      </header>
25
26      <div className="grid grid-cols-3 gap-6">
27        <ProductsWidget data={products} />
28        <SalesWidget data={sales} />
29        <UsersWidget data={users} />
30      </div>
31    </div>
32  );
33}

Différences entre use cache et unstable_cache

Fonctionnalitéuse cacheunstable_cache
SyntaxeDirectiveFonction wrapper
Configuration du tempscacheLife()option revalidate
TaggingcacheTag()option tags
PortéeFonction ou fichierFonction uniquement
StatutStable depuis Next.js 16 (Cache Components)Remplacé par use cache dans Next.js 16

Migrer depuis unstable_cache

Avant (ancienne méthode) :

1import { unstable_cache } from 'next/cache';
2
3const getCachedProducts = unstable_cache(
4  async () => {
5    return fetch('https://api.com/products').then(r => r.json());
6  },
7  ['products'],
8  { revalidate: 3600, tags: ['products'] }
9);

Après (nouvelle méthode) :

1import { cacheTag, cacheLife } from 'next/cache';
2
3async function getProducts() {
4  'use cache';
5  cacheTag('products');
6  cacheLife('hours');
7
8  return fetch('https://api.com/products').then(r => r.json());
9}

Résumé

La directive use cache dans Next.js 16 introduit :

  • Une syntaxe plus simple - caching déclaratif avec une directive
  • Un contrôle du temps flexible - cacheLife avec des profils ou des configurations personnalisées
  • Une revalidation sélective - cacheTag pour un rafraîchissement précis
  • De meilleures performances - gestion optimisée du cache

Dans la Métropole Quantum 2150, où les données circulent à la vitesse de la lumière, un bon caching fait la différence entre une application ultra-rapide et une qui peine à suivre. Maîtrise use cache et tes applications Next.js tourneront à pleine vitesse !

Code de cette leçon : App.tsx
1import React, { useState } from 'react';
2
3// use cache - Nouvelle ère du caching dans Next.js 16
4// Démonstration de la directive 'use cache' et de sa configuration
5
6export default function UseCacheDemo() {
7  const [cacheStrategy, setCacheStrategy] = useState('default');
8  const [data, setData] = useState<any>(null);
9  const [isFetching, setIsFetching] = useState(false);
10
11  const strategies = [
12    { id: 'default', label: 'Cache par défaut', ttl: '30s', description: 'Caching par défaut avec revalidation toutes les 30s' },
13    { id: 'force-cache', label: 'Force Cache', ttl: 'infini', description: 'Les données sont mises en cache de manière permanente' },
14    { id: 'no-store', label: 'No Store', ttl: '0', description: 'Aucun cache - données toujours fraîches' },
15    { id: 'revalidate', label: 'Revalidate', ttl: '60s', description: 'ISR - revalidation toutes les 60 secondes' },
16  ];
17
18  // TODO : Implémente fetchWithCache - simule différentes stratégies de cache
19  // TODO : Montre les différences de temps de réponse selon les stratégies
20
21  return (
22    <div style={{ background: '#0f0f23', minHeight: '100vh', padding: 20, color: '#e0e0e0', fontFamily: 'monospace' }}>
23      <h1 style={{ color: '#64ffda' }}>use cache - Next.js 16</h1>
24      {/* TODO : Sélecteur de stratégie de cache */}
25      {/* TODO : Bouton « Récupérer les données » */}
26      {/* TODO : Affiche le temps de réponse et les données */}
27      {/* TODO : Comparaison des stratégies */}
28    </div>
29  );
30}

Tu as repéré une erreur dans cette leçon ?

Articles utiles