J'adore votre cache ❤️

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

Cet article accompagne la vidéo Love your cache, qui fait partie de la section "Extended Content" du Chrome Dev Summit 2020. Pensez à regarder la vidéo:

Lorsqu'un utilisateur charge votre site une deuxième fois, son navigateur utilise les ressources de son cache HTTP pour accélérer le chargement. Toutefois, les normes de mise en cache sur le Web remontent à 1999. Elles sont définies de manière assez large. Déterminer si un fichier, comme CSS ou une image, peut être récupéré à nouveau sur le réseau plutôt que chargé depuis votre cache n'est pas une science exacte.

Dans cet article, je vais vous présenter une valeur par défaut moderne et pertinente pour la mise en cache, qui n'effectue aucune mise en cache. Mais ce n'est que le comportement par défaut, et c'est bien plus nuancé que de simplement le désactiver. Lisez la suite !

Objectifs

Lorsqu'un site est chargé pour la deuxième fois, vous avez deux objectifs:

  1. Assurez-vous que vos utilisateurs disposent de la version la plus récente disponible. Si vous avez apporté des modifications, celles-ci doivent apparaître rapidement.
  2. Étape 1 en récupérant le moins de données possible sur le réseau

Au sens le plus large, vous devez uniquement envoyer la plus petite modification à vos clients lorsqu'ils chargent à nouveau votre site. De plus, il est difficile de structurer votre site de manière à garantir la distribution la plus efficace de toute modification (vous trouverez plus d'informations à ce sujet ci-dessous et dans la vidéo).

Cela dit, vous avez également d'autres commandes lorsque vous envisagez de mettre en cache 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 nécessaire pour le diffuser. Ou vous avez créé un service worker qui diffusera 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 le Web ne doit pas nécessairement être à l'extrême (cache ou réseau).

Contexte

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

Les internautes normaux n'ont pas ce luxe. Par conséquent, même si nous avons pour objectif principal de garantir aux utilisateurs un bon moment avec leur deuxième chargement, il est également très important de s'assurer qu'ils ne traversent pas de mauvais moments et qu'ils ne soient pas bloqués. (Regardez la vidéo si vous souhaitez m'entendre parler de la façon dont nous avons presque bloqué le site web.dev/live !)

Pour rappel, l'une des raisons les plus courantes de "cache non actualisé" est en fait la valeur par défaut de la mise en cache datant de 1999. Elle repose sur l'en-tête Last-Modified:

Diagramme montrant la durée de mise en cache des différents éléments par le navigateur d'un utilisateur
Les éléments générés à différents moments (en gris) seront mis en cache à des moments différents. Par conséquent, un second chargement peut combiner des éléments mis en cache et des éléments récents.

Chaque fichier que vous chargez est conservé pendant 10% de sa durée de vie actuelle, tel que 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 étant donné 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 JS de mardi et le CSS de la version de vendredi), tout cela étant donné que ces fichiers n'ont pas été mis à jour exactement au même moment.

Le chemin bien éclairé

L'approche par défaut actuelle pour la mise en cache consiste à ne pas effectuer de 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 voir s'il est à jour. Cette requête présente une faible latence, car elle est fournie par un CDN géographiquement proche de chaque utilisateur final.

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

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

Cela indique que le fichier n'est pas valide et que vous devez le valider à partir du réseau avant de pouvoir l'utiliser à nouveau (dans le cas contraire, 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 reçoit une petite réponse 304, mais il coûte une latence, car un utilisateur doit quand même se rendre sur le réseau pour le savoir. Et c'est le principal inconvénient de cette approche. Il peut très bien fonctionner pour les personnes qui disposent d'une connexion rapide dans le Premier monde et pour lesquelles le CDN de votre choix offre une excellente couverture, mais pas pour ceux qui utilisent une connexion mobile plus lente ou une infrastructure médiocre.

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 n'importe quel CDN. Pour Firebase Hosting, vous pouvez inclure cet en-tête dans la section "Hosting" (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"
    }
  }
]

Même si je continue de suggérer cette valeur par défaut raisonnable, elle n'est que la valeur par défaut. Poursuivez votre lecture pour découvrir comment effectuer la mise à jour et modifier les paramètres par défaut.

URL avec empreinte digitale

En incluant un hachage du contenu du fichier dans le nom des éléments, des images, etc. diffusés sur votre site, vous vous assurez que ces fichiers auront toujours un contenu unique. Cela donnera lieu à des fichiers nommés sitecode.af12de.js, par exemple. Lorsque votre serveur répond aux requêtes pour ces fichiers, vous pouvez demander en toute sécurité 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 est une année, en secondes. D'après la spécification, cela équivaut à "éternellement".

Il est important de ne pas générer ces hachages manuellement, car c'est trop de travail manuel ! Pour ce faire, vous pouvez utiliser des outils tels que Webpack, Rollup, etc. Pour en savoir plus, consultez le rapport d'outils.

N'oubliez pas que les URL basées sur l'empreinte numérique ne sont pas les seules à bénéficier de JavaScript. Les éléments tels que les icônes, les fichiers CSS et d'autres fichiers de données immuables peuvent également être nommés de cette façon. (N'oubliez pas de regarder la vidéo ci-dessus pour en savoir un peu plus sur la division du code, qui vous permet d'envoyer moins de code chaque fois que votre site change.)

Quelle que soit l'approche de votre site concernant la mise en cache, ce type de fichiers basés sur les empreintes numériques est extrêmement précieux pour tout site que vous pouvez créer. La plupart des sites ne changent tout simplement pas à chaque version.

Bien entendu, nous ne pouvons pas renommer nos pages "conviviales" destinées aux utilisateurs de cette manière: renommer votre fichier index.html en index.abcd12.html. Cela est impossible, vous ne pouvez pas dire aux utilisateurs d'accéder à une nouvelle URL chaque fois qu'ils chargent votre site. Ces URL « conviviales » ne peuvent pas être renommées ni mises en cache de cette manière, ce qui m'amène à un possible milieu.

Intégralité

Il y a évidemment de la place pour un milieu intermédiaire en ce qui concerne la mise en cache. J'ai présenté deux options extrêmes : mettre en cache never ou mettre en cache toujours. Vous aurez peut-être besoin de mettre en cache un certain nombre de fichiers pendant un certain temps, comme les URL conviviales mentionnées ci-dessus.

Si vous souhaitez mettre en cache ces URL "conviviales" et leur code HTML, il est utile de réfléchir à leurs dépendances, à la manière dont elles peuvent être mises en cache et à l'impact de la mise en cache de leurs URL pendant un certain temps. Examinons une page HTML qui comprend 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 à chargement différé, les utilisateurs qui consultent une version mise en cache de votre code HTML risquent de recevoir une image incorrecte ou manquante, car ils ont toujours mis en cache le /images/foo.jpeg d'origine lorsqu'ils accèdent à nouveau à votre site.

Si vous faites attention, cela ne vous affectera peut-être pas. Toutefois, de manière générale, il est important de garder à l'esprit que votre site, lorsqu'il est mis en cache par vos utilisateurs finaux, n'existe plus uniquement sur vos serveurs. Elle peut plutôt être présente dans des éléments à l'intérieur des caches des navigateurs de l'utilisateur final.

En général, la plupart des guides sur la mise en cache traitent de ce type de paramètre. Voulez-vous mettre en cache une heure, plusieurs heures, etc. Pour définir 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 du contenu opportun qui ne peut généralement être consulté qu'une seule fois par les utilisateurs (comme des articles d'actualité), je pense qu'ils ne doivent jamais être mis en cache. Vous devez donc utiliser la valeur par défaut appropriée ci-dessus. Je pense que nous surestimons souvent l'intérêt de la mise en cache par rapport au désir d'un utilisateur de toujours voir le contenu le plus récent et le plus intéressant, tel qu'une mise à jour critique d'un reportage ou d'un événement en cours.

Options non HTML

Outre HTML, d'autres options pour les fichiers situés au milieu incluent:

  • En général, recherchez les composants qui n'affectent pas les autres utilisateurs.

    • Par exemple, évitez d'utiliser le code CSS, car il modifie l'affichage de votre code HTML.
  • Images volumineuses utilisées dans des articles récents

    • Vos utilisateurs ne consulteront probablement pas un article plus d'une fois. Par conséquent, ne mettez pas en cache les photos ou les images de héros indéfiniment, et ne gaspillez pas votre espace de stockage.
  • Un élément qui représente un élément qui a une durée de vie

    • Il est possible que les données JSON sur la météo ne soient publiées que toutes les heures. Vous pouvez donc mettre en cache le résultat précédent pendant une heure, car il ne changera pas dans votre fenêtre.
    • Les builds d'un projet Open Source peuvent être limités en débit. Par conséquent, mettez en cache une image d'état de compilation jusqu'à ce qu'il soit possible que l'état change.

Résumé

Lorsque les utilisateurs chargent votre site une deuxième fois, cela signifie que vous avez déjà été rassuré : ils veulent revenir sur votre site et profiter davantage de ce que vous proposez. À ce stade, il ne s'agit pas toujours de réduire ce temps de chargement. De nombreuses options sont à votre disposition pour vous assurer que votre navigateur effectue uniquement le travail dont il a besoin pour fournir une expérience à la fois 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. Envisagez d'en utiliser un et d'activer fortement de meilleures stratégies de mise en cache lorsque vous en avez besoin. Merci de votre attention,

Voir aussi

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