J'adore votre cache ❤️

Les utilisateurs qui chargent votre site une deuxième fois utiliseront leur cache HTTP. Assurez-vous donc qu'il fonctionne correctement.

Ce post accompagne la vidéo Love your cache (en anglais) qui fait partie du contenu étendu du Chrome Dev Summit 2020. N'hésitez pas à regarder cette vidéo :

Lorsque les utilisateurs chargent votre site une deuxième fois, leur navigateur utilise les ressources de son cache HTTP pour accélérer le chargement. Toutefois, les normes de mise en cache sur le Web datent de 1999 et sont définies de manière assez large. Déterminer si un fichier, comme un fichier CSS ou une image, peut être extrait à nouveau du réseau ou chargé à partir de votre cache est une science un peu inexacte.

Dans cet article, je vais vous présenter une valeur par défaut raisonnable et moderne pour la mise en cache, qui n'effectue en fait aucune mise en cache. Mais il ne s'agit que de la valeur par défaut. Il est bien sûr plus nuancé que de simplement "désactiver". Lisez la suite.

Objectifs

Lorsqu'un site se charge pour la deuxième fois, vous avez deux objectifs:

  1. Veillez à ce que vos utilisateurs disposent de la version la plus récente disponible. Si vous avez apporté des modifications, elles devraient être répercutées rapidement.
  2. Effectuez l'opération 1 en extrayant le moins possible de données du réseau.

Dans le sens le plus large, vous ne devez envoyer que la plus petite modification à vos clients lorsqu'ils chargent à nouveau votre site. Et structurer votre site pour assurer la distribution la plus efficace de toute modification est un défi (plus d'informations ci-dessous et dans la vidéo).

Cela dit, vous avez également d'autres paramètres à prendre en compte lorsque vous envisagez la mise en cache. Vous avez peut-être décidé de laisser le cache HTTP du navigateur d'un utilisateur conserver votre site pendant une longue période afin qu'aucune requête réseau ne soit requise pour l'afficher. Vous avez également créé un service worker qui diffuse un site entièrement hors connexion avant de vérifier s'il est à jour. Il s'agit d'une option extrême, valide et utilisée pour de nombreuses expériences Web de type application hors connexion, mais il n'est pas nécessaire que le Web soit à l'extrême cache uniquement, ni même à l'extrême réseau uniquement.

Contexte

En tant que développeurs Web, nous sommes tous habitués à l'idée d'avoir un "cache obsolète". Mais nous savons, presque instinctivement, quels outils sont disponibles pour résoudre ce problème : effectuez une "actualisation forcée", ouvrez une fenêtre de navigation privée ou utilisez une combinaison des outils pour les développeurs de votre navigateur pour effacer les données d'un site.

Les utilisateurs ordinaires sur Internet n'ont pas ce luxe. Ainsi, même si notre objectif principal est de nous assurer que nos utilisateurs passent un bon moment avec leur deuxième charge, il est également très important de nous assurer qu'ils ne passent pas de mauvais moment ou ne se retrouvent pas bloqués. (Regardez la vidéo si vous voulez m'entendre parler de la façon dont nous avons failli bloquer le site web.dev/live.)

Pour information, l'une des raisons les plus courantes d'un "cache obsolète" est en réalité la mise en cache par défaut datant de 1999. Il repose sur l'en-tête Last-Modified :

Diagramme illustrant la durée pendant laquelle différents composants sont mis en cache par le navigateur d'un utilisateur
Les composants générés à des moments différents (en gris) seront mis en cache pendant des durées différentes. Une deuxième importation peut donc obtenir une combinaison de composants mis en cache et de composants frais.

Chaque fichier que vous chargez est conservé pendant 10 % supplémentaires de sa durée de vie actuelle, comme le voit votre navigateur. Par exemple, si index.html a été créé il y a un mois, il sera mis en cache par votre navigateur pendant environ trois jours supplémentaires.

C'était une idée bien intentionnée à l'époque, mais compte tenu de la nature étroitement intégrée des sites Web d'aujourd'hui, ce comportement par défaut signifie qu'il est possible qu'un utilisateur dispose de fichiers conçus pour différentes versions de votre site Web (par exemple, le code JavaScript de la version du mardi et le code CSS de la version du vendredi), car ces fichiers n'ont pas été mis à jour exactement au même moment.

Un chemin bien éclairé

Une méthode moderne par défaut pour la mise en cache consiste à n'effectuer aucune mise en cache et à utiliser des CDN pour rapprocher votre contenu des utilisateurs. Chaque fois qu'un utilisateur charge votre site, il accède au réseau pour vérifier s'il est à jour. Cette requête aura une latence faible, car elle sera fournie par un CDN situé géographiquement à proximité de chaque utilisateur final.

Vous pouvez configurer votre hôte Web pour qu'il réponde aux requêtes Web avec cet en-tête :

Cache-Control: max-age=0,must-revalidate,public

Cela signifie que le fichier n'est valide que pendant un court laps de temps et que vous devez le valider sur le réseau avant de pouvoir l'utiliser à nouveau (sinon, il n'est que "suggéré").

Ce processus de validation est relativement peu coûteux en termes d'octets transférés. Si un fichier image volumineux n'a pas changé, votre navigateur recevra une petite réponse 304. Toutefois, il entraîne une latence, car un utilisateur doit toujours accéder au réseau pour le savoir. C'est l'inconvénient principal de cette approche. Il peut fonctionner très bien pour les utilisateurs disposant de connexions rapides dans les pays développés, où votre CDN de choix offre une couverture optimale, mais pas pour ceux qui utilisent des connexions mobiles plus lentes ou une infrastructure de mauvaise qualité.

Quoi qu'il en soit, il s'agit d'une approche moderne qui est utilisée par défaut sur un CDN populaire, Netlify, mais qui peut être configurée sur presque tous les CDN. Pour Firebase Hosting, vous pouvez inclure cet en-tête dans la section d'hébergement de votre fichier firebase.json :

"headers": [
  // Be sure to put this last, to not override other headers
  {
    "source": "**",
    "headers": [ {
      "key": "Cache-Control",
      "value": "max-age=0,must-revalidate,public"
    }
  }
]

Je vous suggère donc de définir cette valeur par défaut, mais ce n'est qu'une suggestion. Lisez la suite pour découvrir comment intervenir et mettre à niveau les valeurs par défaut.

URL avec empreinte

En incluant un hachage du contenu du fichier dans le nom des composants, des images, etc. diffusés sur votre site, vous pouvez vous assurer que ces fichiers auront toujours un contenu unique. Par exemple, les fichiers seront nommés sitecode.af12de.js. Lorsque votre serveur répond aux requêtes de ces fichiers, vous pouvez demander aux navigateurs de vos utilisateurs finaux de les mettre en cache pendant une longue période en les configurant avec cet en-tête :

Cache-Control: max-age=31536000,immutable

Cette valeur correspond à une année, en secondes. Et selon les spécifications, cela équivaut à "pour toujours".

Surtout, ne générez pas ces hachages manuellement. Cela représente trop de travail manuel. Vous pouvez utiliser des outils tels que Webpack, Rollup, etc. pour vous aider. Pour en savoir plus, consultez le rapport sur les outils.

N'oubliez pas que ce n'est pas seulement le code JavaScript qui peut bénéficier des URL avec empreinte : les éléments tels que les icônes, le CSS et d'autres fichiers de données immuables peuvent également être nommés de cette manière. (N'oubliez pas de regarder la vidéo ci-dessus pour en savoir plus sur le fractionnement du code, qui vous permet de publier moins de code chaque fois que votre site change.)

Quelle que soit la méthode de mise en cache de votre site, ces types de fichiers avec empreinte digitale sont extrêmement utiles pour tout site que vous pourriez créer. La plupart des sites ne changent pas à chaque version.

Bien entendu, nous ne pouvons pas renommer nos pages "amicales" destinées aux utilisateurs de cette manière : renommer votre fichier index.html en index.abcd12.html est impossible. Vous ne pouvez pas demander aux utilisateurs d'accéder à une nouvelle URL à chaque fois qu'ils chargent votre site. Ces URL "conviviales" ne peuvent pas être renommées et mises en cache de cette manière, ce qui m'amène à une position intermédiaire possible.

Solution intermédiaire

Il existe évidemment un juste milieu en matière de mise en cache. J'ai présenté deux options extrêmes : ne jamais mettre en cache ou mettre en cache pour toujours. Vous souhaiterez peut-être mettre en cache un certain nombre de fichiers pendant un certain temps, comme les URL "amicales" que j'ai mentionnées ci-dessus.

Si vous souhaitez mettre en cache ces URL "conviviales" et leur code HTML, il est utile de réfléchir aux dépendances qu'elles incluent, à la manière dont elles peuvent être mises en cache et en quoi la mise en cache de leurs URL pendant un certain temps peut vous affecter. Examinons une page HTML qui inclut une image comme celle-ci :

<img src="/images/foo.jpeg" loading="lazy" />

Si vous mettez à jour ou modifiez votre site en supprimant ou en modifiant cette image chargée de manière différée, les utilisateurs qui consultent une version mise en cache de votre code HTML peuvent voir une image incorrecte ou manquante, car ils ont toujours mis en cache l'/images/foo.jpeg d'origine lorsqu'ils reviennent sur votre site.

Soyez prudent, cela ne vous affectera peut-être pas. Mais d'une manière générale, il est important de se rappeler que votre site, lorsqu'il est mis en cache par vos utilisateurs finaux, n'existe plus seulement sur vos serveurs. Il peut plutôt exister en morceaux dans les caches des navigateurs de vos utilisateurs finaux.

En règle générale, la plupart des guides sur la mise en cache parlent de ce type de paramètre : souhaitez-vous mettre en cache pendant une heure, plusieurs heures, etc. Pour configurer ce type de cache, utilisez un en-tête comme celui-ci (qui met en cache pendant 3 600 secondes, soit une heure) :

Cache-Control: max-age=3600,immutable,public

Un dernier point. Si vous créez des contenus d'actualité auxquels les utilisateurs n'ont généralement accès qu'une seule fois (comme des articles d'actualité), je pense qu'ils ne doivent jamais être mis en cache. Vous devez utiliser notre valeur par défaut appropriée ci-dessus. Je pense que nous surestimons souvent la valeur du cache par rapport au désir de l'utilisateur de toujours voir les contenus les plus récents et les plus intéressants, comme une mise à jour critique sur une actualité ou un événement en cours.

Options non HTML

Outre le code HTML, d'autres options sont disponibles pour les fichiers de niveau intermédiaire:

  • En règle générale, recherchez les composants qui n'affectent pas les autres.

    • Par exemple, évitez d'utiliser le langage CSS, car il modifie le rendu de votre code HTML.
  • Images de grande taille utilisées dans des articles d'actualité

    • Vos utilisateurs ne consulteront probablement pas un article plus d'une poignée de fois. Par conséquent, ne mettez pas en cache des photos ou des images principales indéfiniment et ne gaspillez pas d'espace de stockage.
  • Un élément qui représente un élément qui lui-même est associé à une durée de vie.

    • Les données JSON sur la météo ne sont peut-être publiées qu'une fois par heure. Vous pouvez donc mettre en cache le résultat précédent pendant une heure, car il ne changera pas pendant cette période.
    • Les compilations d'un projet Open Source peuvent être limitées en débit. Mettez donc en cache une image de l'état de compilation jusqu'à ce que l'état puisse changer.

Résumé

Lorsque les utilisateurs chargent votre site une deuxième fois, vous avez déjà reçu un vote de confiance : ils veulent revenir et profiter davantage de ce que vous proposez. À ce stade, il ne s'agit pas toujours simplement de réduire le temps de chargement. Vous disposez de nombreuses options pour vous assurer que votre navigateur ne fait que le travail nécessaire pour offrir une expérience rapide et à jour.

La mise en cache n'est pas un nouveau concept sur le Web, mais elle nécessite peut-être une valeur par défaut raisonnable. Nous vous conseillons d'en utiliser une et d'activer fortement les meilleures stratégies de mise en cache lorsque vous en avez besoin. Merci de votre attention,

Voir aussi

Pour obtenir un guide général sur le cache HTTP, consultez Empêcher les requêtes réseau inutiles avec le cache HTTP.