Retour au blog Performance Web - 8 min

Configurer le cache navigateur pour accélérer les visites répétées

Réglez Cache-Control selon le type de fichier : long terme et immutable pour les assets versionnés, no-store pour le HTML personnalisé.

Le cache navigateur évite de retélécharger un fichier déjà vu sur cet appareil. Il accélère la deuxième visite, pas la première. On le règle avec l’en-tête Cache-Control, fichier par fichier : longue durée pour une feuille de style au nom versionné, durée nulle pour une page qui contient un panier ou un jeton.

Ce que le navigateur a le droit de garder

max-age est une durée en secondes. public autorise aussi les caches partagés (proxy, CDN). private limite au navigateur de l’utilisateur. no-store interdit de conserver la réponse. immutable dit que le contenu de cette URL ne changera pas pendant max-age, ce qui évite une revalidation inutile.

s-maxage ne concerne que les caches partagés. Il ne remplace pas max-age pour le navigateur. Si vous ne servez que le navigateur, max-age suffit.

Sans changement de nom de fichier, un max-age d’un an fige le CSS chez ceux qui sont déjà venus. La règle tient en une phrase : l’URL change quand le contenu change, ou la durée reste courte.

Une durée par type de ressource

RessourceEn-tête typePourquoi
CSS, JS, police, avec empreinte dans le nompublic, max-age=31536000, immutableL’ancienne URL peut rester en cache, la nouvelle a un autre nom
Image de contenu (photo article, vignette)public, max-age=259200030 jours, sauf si l’URL est elle aussi versionnée
HTML public et stableno-cache ou max-age=0, must-revalidateLe navigateur redemande, le serveur peut répondre 304
HTML de compte, panier, formulaire avec jetonprivate, no-storeRien ne doit être rejoué depuis le disque
Réponse d’API liée à un utilisateurprivate, no-storeMême motif

no-cache ne veut pas dire « ne pas stocker ». Cela veut dire « revalider avant de réutiliser ». Pour un secret ou un panier, c’est no-store qu’il faut.

Les images lourdes restent lourdes au premier téléchargement : le cache n’enlève pas le besoin de les encoder correctement, voir Images WebP et AVIF. La compression du transfert (Brotli ou gzip) est indépendante et se règle à part : Brotli et gzip.

Où poser l’en-tête

Sur Nginx, un bloc par extension versionnée :

add_header Cache-Control "public, max-age=31536000, immutable"; dans le location des assets au nom hashé.

Sur Apache, Header set Cache-Control "public, max-age=31536000, immutable" dans un FilesMatch limité à ces fichiers.

Ne posez pas cet en-tête sur tout le virtual host. Le HTML hériterait d’un an de cache, y compris une page de connexion. Vérifiez avec une requête qui ne suit que les en-têtes :

curl -sI https://exemple.fr/assets/app.8f3a1c.js

Vous devez voir cache-control et un code 200 (ou 304 si vous revalidez). Contrôlez aussi la page HTML : elle ne doit pas annoncer un an. Un test d’URL sur la page et sur un asset montre tout de suite si les deux répondent la même politique par erreur.

Les constructeurs (Vite, webpack, le versioning de nombreux thèmes) ajoutent l’empreinte au nom. Si le thème sert style.css sans query ni hash, gardez un max-age de quelques heures, ou ajoutez le versioning. Un query string ?v=3 est moins fiable qu’un nom de fichier : certains caches l’ignorent ou le normalisent.

Vider, ou mieux, changer l’URL

Demander aux visiteurs de vider leur cache n’est pas une mise en production. Au déploiement, le HTML neuf pointe vers app.9b2.js. Ceux qui ont encore app.8f3.js le gardent, sans impact. Ceux qui rechargent le HTML obtiennent le nouveau nom.

Le seul cas où un vidage distant est nécessaire : vous avez déjà envoyé un long max-age sur une URL que vous devez corriger d’urgence (fichier légal, script cassé). Vous ne pouvez pas l’effacer des disques. Vous publiez une nouvelle URL et vous faites pointer le HTML dessus. L’ancienne finit par expirer.

Après la mise en ligne, rechargez une fois en navigation privée (cache vide) et une fois en navigation normale. La première mesure le coût à froid. La seconde doit redescendre fortement sur les CSS et JS inchangés. Si la seconde retélécharge tout, l’en-tête n’est pas celui que vous croyez : relisez curl -sI.

Questions fréquentes

Quelle durée de cache pour un fichier CSS ou JavaScript ?

Un an, avec Cache-Control: public, max-age=31536000, immutable, seulement si le nom du fichier change à chaque modification (empreinte dans le nom). Sans empreinte, un long max-age fige l’ancienne version chez le visiteur.

Peut-on mettre la page HTML en cache navigateur longtemps ?

Rarement. Le HTML personnalisé (compte, panier, message) se sert avec no-store ou private et une durée courte. Sinon le visiteur revoit un panier ou un jeton de formulaire périmé.

Cache-Control et Expires, lequel prime ?

Si les deux sont présents, les clients HTTP/1.1 utilisent Cache-Control et ignorent Expires. Posez Cache-Control. Expires seul reste un repli pour de très vieux clients.

Surveiller mes URL