Comment ajouter du cache grâce aux headers
Dans cette leçon on va apprendre à mettre en cache une route React Router 7 via la fonction headers et l’en-tête Cache-Control pour booster la performance.
Dans React Router 7, tu peux contrôler le cache HTTP de tes routes en exportant une fonction headers() directement dans ton module de route. En définissant le header Cache-Control, tu indiques aux navigateurs et aux caches CDN (Vercel, Netlify, Cloudflare…) pendant combien de temps ils peuvent servir une version mise en cache de ta page sans faire d’appel serveur.
Pourquoi mettre en cache avec les headers ?
- Performance : éviter de solliciter la base de données pour chaque visite.
- UX : proposer un temps de réponse quasi instantané pour des pages statiques ou peu changées.
- SEO : un CDN peut pré-valider une page et la servir plus vite aux bots Google.
Note
Ce mécanisme ne remplace pas le refetch côté client () pour les données très dynamiques. On le conseille surtout pour des pages statiques ou des listes qui n’évoluent pas toutes les secondes (ex. page de blog, mentions légales…).
1. État par défaut (en développement)
Par défaut, le serveur de développement Remix/React Router désactive le cache pour garantir que tu vois toujours la dernière version :
1# Tu lances `npm run dev` et dans l'onglet Network de ton navigateur2# tu repères la requête GET /users (par exemple)3Cache-Control: max-age=0
Chaque requête charge donc la donnée depuis le serveur avec un délai artificiel (ex. 100 ms) qui simule l’accès DB.
2. Exporter la fonction headers
Pour ajouter du cache, il suffit d’exporter dans ton fichier de route une fonction headers qui renvoie un objet de HeadersInit :
1export function headers() {2return {3// 300 s côté navigateur, 1 h côté CDN4"Cache-Control": "public, max-age=300, s-maxage=3600"5};6}
Tooltip
s-maxagecible les caches partagés (CDN).
Après avoir déployé sur Vercel/Netlify, tu verras dans l’onglet Network :
1Cache-Control: public, max-age=300, s-maxage=36002X-Cache: HIT # (dépend de ton hébergeur)
3. Options avancées
3.1 stale-while-revalidate
Tu peux aussi autoriser le CDN à servir une version « légèrement périmée » tout en déclenchant un fetch de fond :
1export function headers() {2return {3"Cache-Control": [4"public",5"max-age=300", // 5 min en cache6"s-maxage=3600", // 1 h CDN7"stale-while-revalidate=60" // 1 min pendant le rechargement en arrière-plan8].join(", ")9};10}
Tip
stale-while-revalidatepermet une UX « toujours disponible » lorsque la version cache commence à vieillir.
3.2 Différents niveaux de cache
- Statique (page d’accueil, blog…) :
max-age=86400, s-maxage=86400 - Données semi-dynamiques (liste d’articles) :
max-age=300, s-maxage=600 - Pas de cache (dashboard, données en temps réel) :
max-age=0, s-maxage=0, no-cache, no-store
4. Où ça fonctionne ?
- Local : le serveur de dev Remix ignore les headers Cache-Control
- Production : Vercel, Netlify, Cloudflare et la plupart des hébergeurs respectent tes headers
- Important : le
max-agevaut pour le navigateur client, les-maxagepour le CDN.
Cache local en dev
npm run dev. Il faut déployer pour tester le vrai comportement.5. Points clés à retenir
- Exporte
headers()dans ton module de route pour contrôler le cache. max-age= durée en secondes pour le navigateur.s-maxage= durée pour les caches partagés (CDN).stale-while-revalidate= permet de servir du stale en attendant le rafraîchissement.- Test uniquement en production, car le mode dev ne met rien en cache.
Exercices rapides
- Exercice 1 : Stale while revalidate
- Dans ta route
/blog, ajoutestale-while-revalidate=120. - Déploie sur Netlify et vérifie le header dans l’onglet Network.
- Dans ta route
- Exercice 2 : Routes API
- Crée une resource route
/api/users. - Donne‐lui un cache très court
max-age=10, s-maxage=60. - Observe la différence entre requêtes navigateur et CDN.
- Crée une resource route
- Exercice 3 : Cache conditionnel
- Dans
/settings, exporteheaders()pour renvoyerCache-Control: no-storesi l’utilisateur n’est pas admin. - Implémente la logique dans ton loader ou middleware.
- Dans
Comprendre les concepts fondamentaux
Quelle est la principale différence entre les composants client et serveur dans React ?
Optimisation des performances
Quelle technique est recommandée pour éviter les rendus inutiles dans React ?
Architecture des données
Quel hook permet de gérer les effets de bord dans un composant React ?