Le cache est un principe simple, on stocke une information, un calcul, une donnée pour éviter de faire deux fois le même traitement.

C’est un principe que tu peux retrouver en programmation (memoization) et dans à bien d’autres endroits de ta stack technique.

Plusieurs APIs en action

La mise en cache des ressources dans un navigateur s’articule autour de différentes APIs.
La majorité est implémentée dans les navigateurs evergreen (les navigateurs se mettant à jour automatiquement).

Les APIs abordées dans ce mail se basent sur les possibilités offertes par les requêtes HTTP.
Elles sont utilisables indépendamment les unes des autres.

Le fonctionnement est relativement simple, le serveur ajoute des en-têtes permettant de définir le comportement souhaité.

Il est alors possible de définir la durée de vie de la ressource après laquelle le client doit demander une version à jour ou d’exclure totalement une ressource du cache…


Les headers les plus importants

Cache-Control, ETag et Last-Modified.

Ce sont les headers les plus souvent utilisés.

Ils peuvent avoir différentes valeurs.

J’ai parfois vu des développeurs de plus de 10 ans d’expérience ignorer ces mécanismes.
Les conséquences pour le projet étaient désastreuses.

Inutile de t’expliquer qu'à grande échelle, une mauvaise gestion du cache peut occasionner un problème de charge serveur ou des problèmes de performances.

Je ne reviendrais pas en détail sur toutes les valeurs possibles, pour ça, je te laisse aller jeter un oeil à la documentation…


Cache-Control

Cache-Control est utilisable aussi bien dans les requêtes que dans les réponses HTTP.

Il permet de définir la stratégie à adopter.

Voici quelques-unes des valeurs possibles :

  • max-age=<seconds>
  • no-cache
  • no-store
  • must-revalidate


Chaque valeur décrit un comportement bien spécifique.

L’index.html qui est la racine de ton application sera le plus souvent exclue du cache par exemple.
Alors que la feuille de style principale peut être incluse dans le cache avec une valeur “must-revalidate” qui forcera le client à vérifier qu’il n’y a pas de nouvelle version disponible.

Dans ce cas précis, la requête demande la feuille de style.
Si la feuille de style est à jour, une réponse avec un corps vide sera retournée par le serveur.

Le code HTTP sera le suivant : 304 Not Modified.

Même si ce scénario implique un aller-retour client-serveur, il permet d’éviter un téléchargement inutile de la ressource car le corps de la réponse reste vide.


ETag

ETag permet de générer un identifiant par version de chaque ressource.
Le tag est utilisé directement par le serveur ou le CDN.

Si la ressource est mise à jour, le ETag change systématiquement.
Le plus souvent un hash est alors utilisé pour générer le tag.

Les ETag permettent d’économiser de la bande passante avec un fonctionnement léger.
Ils permettent aussi d’éviter les collisions de mise à jour des ressources.


Last-Modified

Last-Modified permet d’utiliser des valeurs temporelles pour définir la dernière fois qu’une ressource a été modifiée.

Il est alors possible d’envoyer un en-tête If-Modified-Since pour gérer la récupération de la ressource depuis le serveur ou dans le cache.


Des mécanismes simples et d’une importance capitale

Si tu n’avais jamais entendu parler de la gestion du cache dans les navigateurs, je te conseille vivement d’aller faire un tour dans tes devtools et de regarder d’où sont récupérées les ressources quand tu rafraichis une page web.

Ça pourrait t’éviter bien des problèmes à l’avenir.

L’intérêt de la Jamstack est quelle embarque directement les bonnes pratiques de caching et ce out-of-the-box.


Comment GatsbyJS gère le cache ?

Prenons l’exemple de GatsbyJS.

Le build génère des identifiants uniques dans les noms des fichiers importés dans le index.html, ce qui permet de ne pas avoir à gérer l’invalidation des ressources.

Quand une ressource change, son nom change.
Pas besoin de la gérer dynamiquement, cette étape est calculée au moment du build.

Le fait d’utiliser systématiquement un CDN apporte aussi une simplicité vis-à-vis d’un serveur applicatif.
Les CDN sont simples et optimisés pour servir des ressources statiques.