Cache-Control : moins de requêtes, des pages plus rapides

Chaque fois qu’un navigateur charge votre page, il a besoin de vos images, de vos feuilles de style et de vos scripts. Si vous ne lui dites rien, il décide tout seul combien de temps faire confiance à chaque fichier et revérifie souvent auprès du serveur — d’où un flot de réponses 304 Not Modified dans vos journaux. Chaque revalidation ajoute un aller-retour que votre visiteur attend, et du travail pour votre serveur, même quand rien n’a changé. Cache-Control règle cela en disant aux navigateurs combien de temps ils peuvent réutiliser un fichier sans redemander.

Comment fonctionne la mise en cache

Quand un navigateur demande un fichier qu’il n’a pas en cache, il le télécharge. Aux visites suivantes, sans règles de cache, il envoie souvent une requête conditionnelle : « ce fichier a-t-il changé ? » Si la réponse porte un validateur utilisable — un en-tête ETag ou Last-Modified —, le serveur peut répondre 304 Not Modified : pas de nouvelles données, mais quand même un aller-retour. (Sans validateur, il doit renvoyer le fichier entier.) Cache-Control vous permet de sauter complètement cet aller-retour pour les fichiers qui n’en ont pas besoin :

Cache-Control: public, max-age=604800

max-age s’exprime en secondes (604800 = 7 jours). Tant que la copie en cache est fraîche et encore présente, le navigateur la réutilise normalement sans contacter le serveur du tout. Cache-Control a largement remplacé le vieil en-tête Expires, même si les deux fonctionnent encore.

no-cache, no-store et private — trois choses différentes

Ces trois directives se confondent facilement, et leurs noms sont trompeurs :

  • no-cache ne veut pas dire « ne pas mettre en cache ». Cela veut dire qu’un cache peut stocker la réponse, mais doit la revalider auprès du serveur avant de la réutiliser — une consigne « vérifiez avec moi avant de vous fier à votre copie ». Un bon réglage par défaut pour du HTML qui doit être vérifié avant réutilisation ; associez-le à un validateur pour que la réponse puisse être un 304 peu coûteux. (Un HTML stable et public peut, lui, prendre une courte durée de fraîcheur.)
  • no-store dit aux caches HTTP conformes de ne pas conserver la réponse du tout pour une réutilisation ultérieure. Utilisez-le pour les réponses vraiment sensibles (une page qui affiche des coordonnées bancaires) — en plus de vrais contrôles d’accès, car cela n’empêche ni les captures d’écran, ni les téléchargements, ni un intermédiaire non conforme de garder une copie.
  • private signifie que les caches partagés conformes — un CDN, un proxy — ne doivent pas stocker la réponse ; seul le navigateur du visiteur le peut. Utilisez-le pour du contenu personnalisé, comme un tableau de bord après connexion. L’application doit quand même faire respecter le contrôle d’accès et séparer les entrées de cache par utilisateur : private ne répare pas une règle de CDN qui met en cache la mauvaise chose.

Pour la plupart des ressources statiques, vous voulez l’inverse : public avec un max-age long — quand public est sans risque, c’est-à-dire quand la réponse est identique pour chaque visiteur.

Réglages recommandés

  • Ressources statiques dont l’URL change avec leur contenu (CSS, JS, images, polices versionnés) : mettez-les en cache franchement.
  • Ressources sur des URL réutilisables, non versionnées : une durée de vie assez courte pour le degré de péremption que vous tolérez.
  • HTML : revalider ou mettre en cache brièvement ; plus strict (private, no-store) quand c’est personnalisé ou sensible.

Sous Apache, vous définissez les en-têtes avec mod_headers dans .htaccess (là où votre hébergeur autorise ces directives — mod_expires est un module distinct, toujours d’actualité, qui gère plutôt les dates d’expiration) :

<IfModule mod_headers.c>
  # Use only when every matching URL is versioned — the regex can't check that for you
  <FilesMatch "\.(webp|avif|png|jpg|jpeg|gif|svg|woff2|css|js)$">
    Header set Cache-Control "public, max-age=31536000, immutable"
  </FilesMatch>
  # HTML — always revalidate
  <FilesMatch "\.(html|php)$">
    Header set Cache-Control "no-cache"
  </FilesMatch>
</IfModule>

Important : la règle immutable d’un an n’est sans risque que pour des noms de fichiers avec empreinte ou version (style.a1b2c3.css, app.9f2.js). Ce FilesMatch attrape tous les fichiers par extension ; si vos CSS, JS ou images portent des noms simples, non versionnés (style.css, logo.png), il figera des copies périmées dans les navigateurs des visiteurs pendant un an — « on le change rarement » ne suffit pas pour immutable. Soit vous versionnez vos noms de fichiers (voir plus bas) avant d’utiliser cette règle, soit vous donnez aux ressources non versionnées un max-age bien plus court et retirez immutable. Et une fois configuré, vérifiez les en-têtes qu’un visiteur reçoit réellement à l’URL publique : un proxy inverse ou un CDN devant votre serveur peut réécrire ou ignorer la politique de cache d’origine.

Résoudre le problème du « fichier périmé » avec le versionnage

Les longues durées de cache soulèvent une inquiétude : comment vos visiteurs reçoivent-ils votre mise à jour si leur navigateur a pour consigne de garder l’ancien fichier un an ? La réponse, c’est le cache busting — changez le nom de fichier quand le contenu change :

style.css        →  style.a1b2c3.css

Comme l’URL est nouvelle, les navigateurs la téléchargent à neuf, tandis que tous les fichiers inchangés restent en cache. Deux conditions pour que ça marche : mettez à jour toutes les références (HTML, CSS, préchargements, manifeste) vers la nouvelle URL, et laissez l’ancien fichier en ligne jusqu’à ce que le HTML en cache qui y fait encore référence ait expiré — la politique de cache du HTML lui-même fait partie du système. Beaucoup de chaînes de build en production génèrent ces empreintes de contenu quand on les configure pour.

Dites aux navigateurs ce qu’ils peuvent réutiliser sans risque : les visites répétées deviennent plus rapides et moins de requêtes atteignent votre serveur.

Ce qu’il faut faire

  1. Définissez un max-age long (et immutable) sur les ressources statiques — mais seulement une fois leurs noms de fichiers versionnés ; donnez plutôt une durée courte aux fichiers non versionnés.
  2. Gardez le HTML sur no-cache avec un ETag/Last-Modified qui fonctionne, ou une durée courte ; utilisez private pour les pages personnalisées et no-store (plus des contrôles d’accès) pour les pages vraiment sensibles.
  3. Versionnez les noms de fichiers des ressources et mettez à jour chaque référence quand le contenu change.
  4. Activez aussi la compression Gzip/Brotli, et vérifiez les en-têtes réellement livrés à l’URL publique — un CDN peut les modifier.
  5. Revérifiez vos journaux : les requêtes répétées et les 304 sur les ressources versionnées à longue durée de vie devraient chuter (le HTML sur no-cache continuera de se revalider, c’est voulu).

Questions fréquentes

Comment éviter que de longues durées de cache servent un fichier périmé aux visiteurs ?
Utilisez le « cache busting » : donnez au fichier une nouvelle URL chaque fois que son contenu change, par exemple style.css devient style.a1b2c3.css, et mettez à jour toutes les références. Les navigateurs traitent l'URL inconnue comme un téléchargement neuf, tandis que les fichiers inchangés restent en cache. Beaucoup de chaînes de build peuvent générer ces empreintes de contenu quand on les configure pour — et gardez l'ancien fichier en ligne jusqu'à ce que le HTML en cache qui y fait encore référence ait expiré.
Quel max-age définir pour les images, le CSS et le JavaScript ?
Les ressources dont l'URL change quand leur contenu change — images, polices, CSS et JavaScript — peuvent prendre un max-age long (par exemple 31536000) avec immutable. Donnez aux URL réutilisables et non versionnées une durée de vie assez courte pour le degré de péremption que vous tolérez. Gardez le HTML qui doit rester à jour sur no-cache ou une durée courte, et utilisez private ou no-store quand la personnalisation ou la sensibilité l'exige.

Source : “Cache-Control : moins de requêtes, des pages plus rapides” — https://www.siteadvice.be/fr/articles/cache-control/ · © 2026 EUREGIO.NET AG. Tous droits réservés.