La récupération de ressources sur le réseau est à la fois lente et coûteuse:
- Les réponses volumineuses nécessitent de nombreux allers-retours entre le navigateur et le serveur.
- Votre page ne se charge pas tant que toutes ses ressources critiques n'ont pas été entièrement téléchargées.
- Si un utilisateur de votre site dispose d'un forfait de données mobiles limité, chaque requête réseau inutile représente un gaspillage d'argent.
Comment éviter les requêtes réseau inutiles ? Le cache HTTP du navigateur est votre première ligne de défense. Il ne s'agit pas nécessairement de l'approche la plus puissante ou la plus flexible. De plus, vous avez un contrôle limité sur la durée de vie des réponses mises en cache, mais elle est efficace, compatible avec tous les navigateurs et ne nécessite pas beaucoup de travail.
Ce guide vous présente les principes de base d'une implémentation efficace de la mise en cache HTTP.
Compatibilité du navigateur
Le cache HTTP est le nom générique d'un ensemble d'API de plate-forme Web compatibles avec tous les navigateurs:
Cache-Control
ETag
Last-Modified
Fonctionnement du cache HTTP
Toutes les requêtes HTTP effectuées par le navigateur sont d'abord acheminées vers le cache du navigateur pour vérifier s'il existe une réponse mise en cache valide pouvant être utilisée pour répondre à la requête. En cas de correspondance, la réponse est lue à partir du cache, ce qui élimine à la fois la latence du réseau et les coûts des données du transfert.
Le comportement du cache HTTP est contrôlé par une combinaison d'en-têtes de requête et d'en-têtes de réponse. Dans l'idéal, vous contrôlez à la fois le code de votre application Web (qui détermine les en-têtes de requête) et la configuration de votre serveur Web (qui détermine les en-têtes de réponse).
Reportez-vous à l'article Mise en cache HTTP de MDN pour une présentation conceptuelle plus détaillée.
En-têtes de requête: conservez les valeurs par défaut (généralement)
Un certain nombre d'en-têtes importants doivent être inclus dans les requêtes sortantes de votre application Web. Toutefois, le navigateur se charge presque toujours de les définir à votre place lorsqu'il envoie des requêtes. Les en-têtes de requête qui affectent la vérification de l'actualisation, tels que If-None-Match
et If-Modified-Since
, apparaissent en fonction de la compréhension par le navigateur des valeurs actuelles dans le cache HTTP.
C'est une bonne nouvelle: cela signifie que vous pouvez continuer à inclure des balises telles que <img src="my-image.png">
dans votre code HTML, et que le navigateur se charge automatiquement de la mise en cache HTTP pour vous, sans effort supplémentaire.
En-têtes de réponse: configurer votre serveur Web
La partie la plus importante de la configuration de la mise en cache HTTP est les en-têtes que votre serveur Web ajoute à chaque réponse sortante. Les en-têtes suivants sont tous pris en compte dans le comportement efficace de mise en cache:
Cache-Control
- Le serveur peut renvoyer une directive
Cache-Control
pour spécifier comment et pendant combien de temps le navigateur et les autres caches intermédiaires doivent mettre en cache la réponse individuelle. ETag
.- Lorsque le navigateur trouve une réponse mise en cache arrivée à expiration, il peut envoyer un petit jeton (généralement un hachage du contenu du fichier) au serveur pour vérifier si le fichier a été modifié. Si le serveur renvoie le même jeton, le fichier est identique. Il n'est donc pas nécessaire de le télécharger à nouveau.
Last-Modified
- Cet en-tête remplit la même fonction que
ETag
, mais utilise une stratégie basée sur le temps pour déterminer si une ressource a été modifiée, par opposition à la stratégie basée sur le contenu deETag
.
Certains serveurs Web permettent de définir ces en-têtes par défaut. D'autres laissent de côté les en-têtes, sauf si vous les configurez explicitement. Les détails spécifiques de la configuration des en-têtes varient considérablement selon le serveur Web que vous utilisez. Pour obtenir les informations les plus précises, nous vous conseillons de consulter la documentation de votre serveur.
Pour vous éviter d'avoir à effectuer des recherches, voici les instructions de configuration de quelques serveurs Web courants:
Le fait d'omettre l'en-tête de réponse Cache-Control
ne désactive pas la mise en cache HTTP.
Au lieu de cela, les navigateurs devinent efficacement le type de comportement de mise en cache le plus logique pour un type de contenu donné.
Il y a de fortes chances que vous souhaitiez disposer de plus de contrôle que cela. Vous devrez donc prendre le temps de configurer vos en-têtes de réponse.
Quelles valeurs d'en-tête de réponse devez-vous utiliser ?
Vous devez couvrir deux scénarios importants lorsque vous configurez les en-têtes de réponse de votre serveur Web.
Mise en cache de longue durée pour les URL avec gestion des versions
Supposons que votre serveur demande aux navigateurs de mettre en cache un fichier CSS pendant un an (Cache-Control: max-age=31536000
), mais que votre concepteur vient d'effectuer une mise à jour d'urgence que vous devez implémenter immédiatement. Comment demandez-vous aux navigateurs de mettre à jour la copie mise en cache "obsolète" du fichier ?
C'est impossible, du moins pas sans modifier l'URL de la ressource.
Une fois que le navigateur a mis en cache la réponse, la version mise en cache est utilisée jusqu'à ce qu'elle ne soit plus à jour (comme déterminé par max-age
ou expires
), ou jusqu'à ce qu'elle soit supprimée du cache pour une autre raison (par exemple, lorsque l'utilisateur vide le cache de son navigateur). Par conséquent, différents utilisateurs peuvent finir par charger des versions différentes du fichier lors de la construction de la page: les utilisateurs qui viennent de récupérer la ressource utilisent la nouvelle version, tandis que ceux qui ont mis en cache une copie antérieure (mais toujours valide) utilisent une version plus ancienne.
Pour obtenir à la fois la mise en cache côté client et des mises à jour rapides, vous pouvez modifier l'URL de la ressource et forcer l'utilisateur à télécharger la nouvelle réponse chaque fois que son contenu change. Pour ce faire, vous devez généralement intégrer une empreinte du fichier ou un numéro de version dans son nom de fichier: par exemple, style.x234dff.css
.
Lorsque vous répondez à des requêtes d'URL contenant une empreinte ou des informations de version, et dont le contenu n'est jamais destiné à changer, ajoutez Cache-Control: max-age=31536000
à vos réponses.
La définition de cette valeur indique au navigateur que s'il doit charger la même URL à tout moment au cours de l'année à venir (31 536 000 secondes, la valeur maximale acceptée), il peut immédiatement l'utiliser dans le cache HTTP, sans avoir à envoyer de requête réseau à votre serveur Web. C'est super ! Vous avez immédiatement gagné en fiabilité et en vitesse en évitant le réseau.
Des outils de compilation tels que webpack peuvent automatiser le processus d'attribution d'empreintes de hachage aux URL de vos éléments.
Nouvelle validation du serveur pour les URL sans version
Malheureusement, les versions des URL que vous chargez ne sont pas toutes gérées par version. Vous ne pouvez peut-être pas inclure d'étape de compilation avant de déployer votre application Web. Vous ne pouvez donc pas ajouter de hachages à vos URL d'éléments. De plus, chaque application Web a besoin de fichiers HTML, qui n'incluent presque jamais d'informations de gestion des versions. En effet, personne ne risque d'utiliser votre application Web s'il doit se souvenir que l'URL à consulter est https://example.com/index.34def12.html
. Que pouvez-vous faire pour ces URL ?
La mise en cache HTTP seule n'est pas assez puissante pour éviter complètement le réseau. (Ne vous inquiétez pas : vous découvrirez bientôt les service workers, qui offrent une assistance supplémentaire.) Vous pouvez toutefois prendre certaines mesures pour vous assurer que les requêtes réseau sont aussi rapides et efficaces que possible.
Les valeurs Cache-Control
suivantes peuvent vous aider à affiner où et comment les URL sans version sont mises en cache:
no-cache
indique au navigateur qu'il doit revalider avec le serveur à chaque fois avant d'utiliser une version mise en cache de l'URL.no-store
indique au navigateur et aux autres caches intermédiaires (tels que les CDN) de ne jamais stocker de version du fichier.private
: les navigateurs peuvent mettre en cache le fichier, mais pas les caches intermédiaires.public
: n'importe quel cache peut stocker la réponse.
Consultez l'annexe: organigramme Cache-Control
pour visualiser le processus de sélection des valeurs Cache-Control
à utiliser. Cache-Control
peut également accepter une liste d'instructions séparées par une virgule. Consultez l'annexe: exemples Cache-Control
.
Il peut également être utile de définir ETag
ou Last-Modified
.
Comme indiqué dans les en-têtes de réponse, ETag
et Last-Modified
ont tous deux le même objectif: déterminer si le navigateur doit télécharger à nouveau un fichier mis en cache qui a expiré. Nous vous recommandons d'utiliser ETag
, car il est plus précis.
Supposons que 120 secondes se soient écoulées depuis la récupération initiale et que le navigateur a lancé une nouvelle requête pour la même ressource. Le navigateur vérifie d'abord le cache HTTP et trouve la réponse précédente.
Malheureusement, le navigateur ne peut pas utiliser la réponse précédente, car elle a expiré. À ce stade, le navigateur peut envoyer une nouvelle requête et récupérer la nouvelle réponse complète. Cette approche n'est toutefois pas efficace, car si la ressource n'a pas changé, il n'y a aucune raison de télécharger à nouveau les informations qui se trouvent déjà dans le cache.
C'est le problème que les jetons de validation ETag
sont conçus pour résoudre. Le serveur génère et renvoie un jeton arbitraire, qui est généralement un hachage ou une autre empreinte du contenu du fichier.
Le navigateur n'a pas besoin de savoir comment l'empreinte est générée. Il doit seulement l'envoyer au serveur lors de la prochaine requête. Si l'empreinte est toujours la même, la ressource n'a pas changé et le navigateur peut ignorer le téléchargement.
Définir ETag
ou Last-Modified
rend la requête de revalidation beaucoup plus efficace, car elle permet de déclencher les en-têtes de requête If-Modified-Since
ou If-None-Match
mentionnés dans En-têtes de requête.
Lorsqu'un serveur Web correctement configuré voit ces en-têtes de requête entrants, il peut confirmer si la version de la ressource que le navigateur possède déjà dans son cache HTTP correspond à la dernière version sur le serveur Web. En cas de correspondance, le serveur peut répondre avec une réponse HTTP 304 Not Modified
, ce qui équivaut à "Hey, continue d'utiliser ce que tu as déjà !" Étant donné que très peu de données sont à transférer lors de l'envoi de ce type de réponse, c'est généralement beaucoup plus rapide que de renvoyer une copie de la ressource demandée.
Résumé
Le cache HTTP est un moyen efficace d'améliorer les performances de chargement, car il réduit le nombre de requêtes réseau inutiles. Il est compatible avec tous les navigateurs et ne demande pas trop de travail à configurer.
Les configurations Cache-Control
suivantes constituent un bon point de départ:
Cache-Control: no-cache
pour les ressources qui doivent être revalidées avec le serveur avant chaque utilisation.Cache-Control: no-store
pour les ressources qui ne doivent jamais être mises en cache.Cache-Control: max-age=31536000
pour les ressources avec gestion des versions.
L'en-tête ETag
ou Last-Modified
peut vous aider à revalider plus efficacement les ressources de cache arrivées à expiration.
En savoir plus
Si vous souhaitez approfondir l'utilisation de l'en-tête Cache-Control
, consultez le guide Caching best practices & max-age gotchas de Jake Archibald.
Consultez la section Vous aimez votre cache pour savoir comment optimiser son utilisation pour les visiteurs connus.
Annexe: Conseils supplémentaires
Si vous avez plus de temps, voici d'autres moyens d'optimiser votre utilisation du cache HTTP:
- Utilisez des URL cohérentes. Si vous affichez le même contenu sur des URL différentes, le navigateur le récupère et le stocke plusieurs fois.
- Réduisez les pertes d'utilisateurs. Si une partie d'une ressource (telle qu'un fichier CSS) se met à jour fréquemment, mais pas le reste du fichier (comme avec le code de bibliothèque), envisagez de diviser le code fréquemment mis à jour dans un fichier distinct et d'utiliser une stratégie de mise en cache de courte durée pour le code fréquemment mis à jour, ainsi qu'une stratégie de mise en cache longue pour le code qui ne change pas souvent.
- Si un certain degré d'obsolescence est acceptable dans votre stratégie
Cache-Control
, envisagez d'utiliser la nouvelle directivestale-while-revalidate
.
Annexe: Organigramme Cache-Control
Annexe: Exemples de Cache-Control
Valeur Cache-Control |
Explication |
---|---|
max-age=86400 |
La réponse peut être mise en cache par les navigateurs et les caches intermédiaires pendant une journée maximale (60 secondes x 60 minutes x 24 heures). |
private, max-age=600 |
La réponse peut être mise en cache par le navigateur, mais pas par les caches intermédiaires, pendant un maximum de 10 minutes (60 secondes x 10 minutes). |
public, max-age=31536000 |
La réponse peut être stockée par n'importe quel cache pendant un an. |
no-store |
La réponse ne peut pas être mise en cache et doit être extraite entièrement à chaque requête. |