Mise en cache
Introduction
La mise en cache est une technique permettant de réutiliser un contenu précédemment téléchargé. Elle offre un avantage significatif en termes de performance en évitant de rejouer de coûteuses requêtes. La mise en cache facilite la montée en charge d’une application, en réduisant le trafic sur le réseau à destination du serveur d’origine. Un vieux dicton dit que “la requête la plus rapide est celle que vous n’avez pas à faire ” et la mise en cache est l’un des principaux moyens d’éviter d’avoir à refaire des requêtes.
La mise en cache sur le web s’appuie sur trois principes fondamentaux : mettre en cache autant que possible, aussi longtemps que possible et aussi près que possible des utilisateurs finaux.
Mettre en cache autant que vous le pouvez. Lorsque l’on s’intéresse aux données pouvant être mises en cache, il est important de débuter en identifiant les réponses statiques et dynamiques, qui évoluent ou non en fonction du contexte d’appel. Généralement, les réponses statiques, ne changeant pas, peuvent être mises en cache. Mettre en cache les réponses statiques permettra de les partager entre les utilisateurs. Les contenus dynamiques nécessitent, quant à eux, une analyse plus poussée.
Mettre en cache aussi longtemps que possible. La durée de mise en cache d’une ressource dépend fortement de sa sensibilité et de son contenu. Une ressource JavaScript versionnée peut être mise en cache pendant très longtemps, alors qu’une ressource non versionnée peut nécessiter une durée de cache plus courte afin de garantir aux utilisateurs de disposer des données a jour.
Cachez le plus près possible des utilisateurs finaux. Une mise en cache proche des utilisateurs réduit les temps de téléchargement en réduisant les latences réseau. Par exemple, pour une ressource mise en cache sur le navigateur de l’utilisateur, la requête ne sera jamais envoyée sur le réseau et le temps de téléchargement sera aussi rapide que les I/O de la machine. Pour les premiers visiteurs, ou les visiteurs qui n’ont pas encore leurs données cachées, un CDN est généralement la prochaine localisation d’une ressource cachée. Dans la plupart des cas, il sera plus rapide de récupérer une ressource à partir d’un cache local ou d’un CDN que sur le serveur d’origine.
Les architectures Web impliquent généralement une mise en cache en plusieurs niveaux. Par exemple une requête HTTP peut être mise en cache de différentes manière :
- dans le cache du navigateur ;
- dans le cache d’un service worker dans le navigateur ;
- dans une passerelle partagée ;
- au niveau des CDN, qui offrent la possibilité de mettre en cache à proximité des utilisateurs ;
- dans un proxy de cache en amont des applications pour réduire la charge sur les serveurs back-end ;
- au niveau de l’application et de la base de données.
Ce chapitre explique comment les ressources sont mises en cache dans les navigateurs Web.
Présentation de la mise en cache HTTP
Pour qu’un client HTTP mette en cache une ressource, il doit répondre a deux questions :
- “Combien de temps dois-je mettre en cache ?”
- “Comment puis-je valider que le contenu est encore frais ?”
Lorsqu’un navigateur Web envoie une réponse à un client, il inclut généralement dans sa réponse des en-têtes qui indiquent si la ressource peut être mise en cache, pour combien de temps et quel est son âge. La RFC 7234 traite plus en détail de ce point dans la section 4.2 (Freshness) et 4.3 (Validation).
Les en-têtes de réponse HTTP généralement utilisées pour transmettre la durée de vie sont :
-
Cache-Control
vous permet de configurer la durée de vie du cache (c’est-à-dire sa durée de validité). Expires
fournit une date ou une heure d’expiration (c.-à-d. quand exactement celle-ci expire).
Cache-Control
est prioritaire si les deux champs sont renseignés. Ces en-têtes sont abordés plus en détail ci-dessous.
Les en-têtes de réponse HTTP permettant de valider les données stockées en cache, c’est à dire donner les informations nécessaires pour comparer une ressource à sa contrepartie côté serveur :
Last-Modified
indique quand la ressource a été modifiée pour la dernière fois.ETag
fournit l’identifiant unique d’une ressource.
ETag
est prioritaire si les deux en-têtes sont renseignés. Ces en-têtes sont abordés plus en détail ci-dessous.
L’exemple ci-dessous contient un extrait d’un en-tête requête/réponse du fichier main.js de HTTP Archive. Ces en-têtes indiquent que la ressource peut être mise en cache pendant 43 200 secondes (12 heures), et qu’elle a été modifiée pour la dernière fois il y a plus de deux mois (différence entre les en-têtes Last-Modified
et Date
).
> GET /static/js/main.js HTTP/1.1
> Host: httparchive.org
> User-agent: curl/7.54.0
> Accept: */*
< HTTP/1.1 200
< Date: Sun, 13 Oct 2019 19:36:57 GMT
< Content-Type: application/javascript; charset=utf-8
< Content-Length: 3052
< Vary: Accept-Encoding
< Server: gunicorn/19.7.1
< Last-Modified: Sun, 25 Aug 2019 16:00:30 GMT
< Cache-Control: public, max-age=43200
< Expires: Mon, 14 Oct 2019 07:36:57 GMT
< ETag: "1566748830.0-3052-3932359948"
L’outil RedBot.org vous permet d’entrer une URL et de voir un rapport détaillé de la façon dont la réponse sera mise en cache en fonction de ses en-têtes. Par exemple,un test pour l’URL ci-dessus produirait ce qui suit :
Si aucun en-tête de mise en cache n’est renseigné dans la réponse, alors l’application peut mettre en cache en suivant une heuristique générique. La plupart des clients implémentent une variation de l’heuristique suggérée par le RFC, qui est 10 % du temps depuis le Last-Modified
. Toutefois, certains peuvent mettre la réponse en cache indéfiniment. Il est donc important de définir des règles de mise en cache spécifiques pour s’assurer que vous maîtrisez la cachabilité.
72 % des réponses HTTP sont servies avec un en-tête Cache-Control
, et 56 % des réponses sont servies avec un en-tête Expires
. Cependant, 27 % des réponses n’utilisaient ni l’un ni l’autre, et peuvent alors être mises en cache en suivant cette heuristique. C’est un constat partagé par les sites pour ordinateurs de bureau et les sites mobiles.
Quel type de contenu met-on en cache ?
Une ressource mise en cache est stockée par le client pendant un certain temps et peut être réutilisée ultérieurement. Pour les requêtes HTTP, 80 % des réponses peuvent certainement être mises en cache, ce qui signifie qu’un système de cache peut les stocker. En dehors de ça,
- 6 % des requêtes ont un Time To Live (TTL) de 0 seconde, qui invalide immédiatement une entrée en cache.
- 27 % sont mis en cache par heuristique, à cause d’un
Cache-Control
manquant en en-tête. - 47 % sont mis en cache pendant plus de 0 seconde.
Les autres réponses ne peuvent pas être stockées dans le cache du navigateur.
Le tableau ci-dessous détaille les TTL du cache pour les requêtes en provenance d’ordinateurs de bureau. La plupart des types de contenu sont mis en cache, mais les ressources CSS semblent toujours être mises en cache à des valeurs TTL élevées.
Percentiles TTL du cache des ordinateurs de bureau (Heures) | |||||
---|---|---|---|---|---|
10 | 25 | 50 | 75 | 90 | |
Audio | 12 | 24 | 720 | 8,760 | 8,760 |
CSS | 720 | 8,760 | 8,760 | 8,760 | 8,760 |
Police d’écriture | < 1 | 3 | 336 | 8,760 | 87,600 |
HTML | < 1 | 168 | 720 | 8,760 | 8,766 |
Image | < 1 | 1 | 28 | 48 | 8,760 |
Autre | < 1 | 2 | 336 | 8,760 | 8,760 |
Script | < 1 | < 1 | 1 | 6 | 720 |
Texte | 21 | 336 | 7,902 | 8,357 | 8,740 |
Vidéo | < 1 | 4 | 24 | 24 | 336 |
XML | < 1 | < 1 | < 1 | < 1 | < 1 |
Bien que la plupart des TTL médians sont élevées, les percentiles inférieurs mettent en évidence certaines occasions manquées de mise en cache. Par exemple, le TTL médian pour les images est de 28 heures, mais le 25e percentile n’est que d’une à deux heures et le 10e percentile indique que 10 % du volume d’images en cache l’est pendant moins d’une heure.
En explorant plus en détail les possibilités de mise en cache par type de contenu dans la figure 16.5 ci-dessous, nous pouvons voir qu’environ la moitié de toutes les réponses HTML sont considérées comme non cachables. De plus, 16 % des images et des scripts ne peuvent pas être mis en cache.
Les mêmes données pour le mobile sont présentées ci-dessous. Comme on peut le voir, la mise en cache des types de contenu est similaire entre les ordinateurs de bureau et les mobiles.
Cache-Control
vs Expires
Dans HTTP/1.0, l’en-tête Expires
était utilisé pour indiquer la date/heure après laquelle la réponse était considérée comme périmée. Sa valeur est un horodatage, par exemple :
Expires: Thu, 01 Dec 1994 16:00:00 GMT
HTTP/1.1 a introduit l’en-tête Cache-Control
, et la plupart des clients modernes supportent les deux en-têtes. Cet en-tête est beaucoup plus extensible, via des directives de mise en cache. Par exemple :
no-store
peut être utilisé pour indiquer qu’une ressource ne doit pas être mise en cache.max-age
peut être utilisé pour indiquer une durée de vie.must-revalidate
indique au client que la ressource mise en cache doit être revalidée avec une requête conditionnelle avant son utilisation.private
indique qu’une réponse ne doit être mise en cache que par un navigateur, et non par un intermédiaire qui servirait plusieurs clients.
53 % des réponses HTTP incluent un en-tête Cache-Control
avec la directive max-age
, et 54 % incluent l’en-tête Expires
. Cependant, seulement 41 % de ces réponses utilisent les deux en-têtes, ce qui signifie que 13 % des réponses sont basées uniquement sur l’ancien en-tête Expires
.
Directives Cache-Control
La specification HTTP/1.1 inclut de multiples directives qui peuvent être utilisées dans l’en-tête de réponse Cache-Control
et sont détaillées ci-dessous. Notez que plusieurs directives peuvent être utilisées dans une seule réponse.
Directive | Description |
---|---|
max-age | Indique le nombre de secondes pendant lesquelles une ressource peut être mise en cache. |
public | N’importe quel cache peut stocker la réponse. |
no-cache | Une entrée en cache doit être revalidée avant son utilisation. |
must-revalidate | Une entrée en cache périmée doit être revalidée avant son utilisation. |
no-store | Indique qu’une réponse ne doit pas être mise en cache. |
private | La réponse est destinée à un utilisateur spécifique et ne doit pas être stockée par des caches partagés. |
no-transform | Aucune transformation ou conversion ne doit être effectuée sur cette ressource. |
proxy-revalidate | Identique à must-revalidate mais pour les caches partagés. |
s-maxage | Identique à l’âge maximum mais pour les caches partagés. |
immutable | Indique que l’entrée en cache ne changera jamais, et qu’une revalidation n’est pas nécessaire. |
stale-while-revalidate | Indique que le client est prêt à accepter une réponse périmée tout en vérifiant de manière asynchrone en arrière-plan l’existence d’une ressource plus fraiche. |
stale-if-error | Indique que le client est prêt à accepter une réponse périmée même si la vérification qu’une ressource plus fraiche échoue. |
Cache-Control
directives.
Par exemple, cache-control:public, max-age=43200
indique qu’une entrée mise en cache doit être stockée pendant 43.200 secondes et qu’elle peut être stockée par tous les caches.
La figure 16.9 ci-dessus illustre les 15 directives Cache-Control
les plus utilisées sur les sites Web mobiles. Les résultats pour les sites destinés aux ordinateurs de bureau et les sites mobiles sont très similaires. Il y a quelques observations intéressantes sur la popularité de ces directives de cache :
max-age
est utilisé par presque 75 % des en-têtesCache-Control
, etno-store
est utilisé par 18 %.public
(publique) est rarement nécessaire car les entrées en cache sont supposéespublic
à moins queprivate
(privé) ne soit spécifié. Environ 38 % des réponses incluentpublic
.- La directive
immutable
est relativement nouvelle, introduite en 2017 et est supportée par Firefox et Safari. Son utilisation a augmenté à 3,4 % et elle est largement utilisée dans les réponses des tierces parties de Facebook et Google.
Un autre ensemble intéressant de directives à faire apparaître dans cette liste sont pre-check
et post-check
, qui sont utilisées dans 2,2 % des en-têtes Cache-Control
(environ 7,8 millions de réponses). Cette paire d’en-têtes a été introduite dans Internet Explorer 5 pour fournir une validation en arrière-plan et a rarement été implémentée correctement par les sites web. 99,2 % des réponses utilisant ces en-têtes avaient utilisé la combinaison pre-check=0
et post-check=0
. Quand ces deux directives sont mises à 0, alors les deux directives sont ignorées. Il semble donc que ces directives n’aient jamais été utilisées correctement !
Il y a plus de 1 500 directives erronées utilisées dans 0,28 % des réponses. Ces directives sont ignorées par les clients, comprennent des erreurs d’orthographe telles que nocache
, s-max-age
, smax-age
et maxage
. Il y a aussi de nombreuses directives inexistantes comme max-stale
, proxy-public
, subsrogate-control
, etc.
Cache-Control
: no-store
, no-cache
et max-age=0
Lorsqu’une réponse ne doit pas être mise en cache, la directive Cache-Control
no-store
doit être utilisée. Si cette directive n’est pas utilisée, alors la réponse peut être mise en cache.
Il y a quelques erreurs courantes, commises lorsqu’on essaie de configurer une réponse pour qu’elle ne puisse pas être mise en cache :
- configurer
Cache-Control: no-cache
peut donner l’impression que la ressource ne doit pas être mise en cache. En réalité,no-cache
précise que l’entrée mise en cache doit être revalidée avant d’être utilisée et n’indique pas que la ressource ne peut pas être mise en cache. Cache-Control: max-age=0
fixe le TTL à 0 seconde, mais ce n’est pas la même chose que de ne pas pouvoir mettre en cache. Quandmax-age
est fixé à 0, la ressource est stockée dans le cache du navigateur et immédiatement invalidée. Le navigateur doit donc effectuer une requête conditionnelle pour valider la fraîcheur de la ressource.
Fonctionnellement, no-cache
et max-age=0
sont similaires, puisqu’ils nécessitent tous deux la revalidation d’une ressource mise en cache. La directive no-cache
peut aussi être utilisée avec une directive max-age
supérieure à 0.
Plus de 3 millions de réponses comprennent la combinaison de no-store
, no-cache
, et max-age=0
. Parmi ces directives, no-store
est prioritaire et les autres directives sont simplement redondantes.
18 % des réponses comprennent no-store
et 16,6 % des réponses comprennent à la fois no-store
et no-cache
. Puisque no-store
a la priorité, la ressource n’est finalement pas cachable.
La directive max-age=0
est présente sur 1,1 % des réponses (plus de quatre millions de réponses) où no-store
n’est pas présent. Ces ressources seront mises en cache dans le navigateur mais devront être revalidées car elles sont immédiatement expirées.
Comment les TTL de cache se comparent-ils à l’âge des ressources ?
Jusqu’à présent, nous avons parlé de la façon dont les serveurs Web indiquent à un client ce qui peut être mis en cache, et pendant combien de temps. Lors de la conception des règles de mise en cache, il est également important de comprendre l’âge du contenu que vous servez.
Lorsque vous choisissez un cache TTL, demandez-vous : “à quelle fréquence allez-vous mettre à jour ces ressources ?” et “quelle est la sensibilité de leur contenu ?”. Par exemple, si une Hero Image va être modifiée peu fréquemment, alors cachez-la avec un TTL très long. Si vous vous attendez à ce qu’une ressource JavaScript soit modifiée fréquemment, alors versionnez-la puis mettez-la en cache avec un long TTL ou cachez-la avec un TTL plus court.
Le graphique ci-dessous illustre l’âge relatif des ressources par type de contenu, et vous pouvez lire une analyse plus détaillée ici. Le HTML tend à être le type de contenu ayant l’âge le plus court, et un très grand pourcentage des ressources traditionnellement mises en cache (scripts, CSS, et polices d’écriture) ont plus d’un an !
En comparant la capacité de mise en cache d’une ressource à son âge, nous pouvons déterminer si le TTL est approprié ou trop faible. Par exemple, la ressource servie par la réponse ci-dessous a été modifiée pour la dernière fois le 25 août 2019, ce qui signifie qu’elle avait 49 jours au moment où elle a été servie. L’en-tête Cache-Control
indique que nous pouvons la mettre en cache pendant 43 200 secondes, soit 12 heures. La ressource est largement assez vieille pour mériter qu’on se demande si un TTL plus long serait approprié.
< HTTP/1.1 200
< Date: Sun, 13 Oct 2019 19:36:57 GMT
< Content-Type: application/javascript; charset=utf-8
< Content-Length: 3052
< Vary: Accept-Encoding
< Server: gunicorn/19.7.1
< Last-Modified: Sun, 25 Aug 2019 16:00:30 GMT
< Cache-Control: public, max-age=43200
< Expires: Mon, 14 Oct 2019 07:36:57 GMT
< ETag: "1566748830.0-3052-3932359948"
Dans l’ensemble, 59 % des ressources servies sur le Web ont un TTL de cache trop court par rapport à l’âge de leur contenu. De plus, le delta médian entre le TTL et l’âge est de 25 jours.
Si l’on compare les ressources du domaine principal et celles des tierces parties, on constate que 70 % des ressources du domaine principal peuvent bénéficier d’une durée de vie plus longue. Cela met clairement en évidence la nécessité d’accorder une attention particulière à ce qui peut être mis en cache, puis de s’assurer que la mise en cache est configurée correctement.
Client | 1ere partie | 3e partie | Global |
---|---|---|---|
Bureau | 70.7 % | 47.9 % | 59.2 % |
Mobile | 71.4 % | 46.8 % | 59.6 % |
Validation de la fraîcheur des informations
Les en-têtes HTTP utilisés pour valider les réponses stockées dans un cache sont Last-Modified
et ETag
. L’en-tête Last-Modified
fait exactement ce que son nom implique et fournit l’heure à laquelle l’objet a été modifié pour la dernière fois. L’en-tête ETag
fournit un identifiant unique pour le contenu.
Par exemple, la réponse ci-dessous a été modifiée pour la dernière fois le 25 août 2019 et elle a une valeur ETag
de "1566748830.0-3052-3932359948"
.
< HTTP/1.1 200
< Date: Sun, 13 Oct 2019 19:36:57 GMT
< Content-Type: application/javascript; charset=utf-8
< Content-Length: 3052
< Vary: Accept-Encoding
< Server: gunicorn/19.7.1
< Last-Modified: Sun, 25 Aug 2019 16:00:30 GMT
< Cache-Control: public, max-age=43200
< Expires: Mon, 14 Oct 2019 07:36:57 GMT
< ETag: "1566748830.0-3052-3932359948"
Un client peut envoyer une requête conditionnelle pour valider une entrée en cache en utilisant la valeur Last-Modified
dans un en-tête de requête nommé If-Modified-Since
. De même, il pourrait aussi valider la ressource avec un en-tête de requête If-None-Match
, qui valide par rapport à la valeur ETag
que le client a pour la ressource dans son cache.
Dans l’exemple ci-dessous, le cache semble toujours valide, et un HTTP 304
a été renvoyé sans contenu. Cela permet d’économiser le téléchargement de la ressource elle-même. Si l’entrée de cache n’était plus fraîche, alors le serveur aurait répondu avec un 200
et la ressource mise à jour qui aurait dû être téléchargée à nouveau.
> GET /static/js/main.js HTTP/1.1
> Host: www.httparchive.org
> User-Agent: curl/7.54.0
> Accept: */*
> If-Modified-Since: Sun, 25 Aug 2019 16:00:30 GMT
< HTTP/1.1 304
< Date: Thu, 17 Oct 2019 02:31:08 GMT
< Server: gunicorn/19.7.1
< Cache-Control: public, max-age=43200
< Expires: Thu, 17 Oct 2019 14:31:08 GMT
< ETag: "1566748830.0-3052-3932359948"
< Accept-Ranges: bytes
Dans l’ensemble, 65 % des réponses sont servies avec un en-tête Last-Modified
, 42 % sont servies avec un ETag
, et 38 % utilisent les deux. Cependant, 30 % des réponses n’incluent ni un en-tête Last-Modified
ni un en-tête ETag
.
Validité des dates
Le format des en-têtes HTTP utilisés pour transmettre les horodatages, et le format de ceux-ci, sont importants. L’en-tête Date
indique quand la ressource a été servie à un client. L’en-tête Last-Modified
indique quand une ressource a été modifiée pour la dernière fois sur le serveur. Et l’en-tête Expires
est utilisé pour indiquer combien de temps une ressource doit être mise en cache (à moins qu’un en-tête Cache-Control
soit présent).
Tous ces en-têtes HTTP utiliser des dates sous forme de chaine de carractères pour représenter des horodatages.
Par exemple :
> GET /static/js/main.js HTTP/1.1
> Host: httparchive.org
> User-Agent: curl/7.54.0
> Accept: */*
< HTTP/1.1 200
< Date: Sun, 13 Oct 2019 19:36:57 GMT
< Content-Type: application/javascript; charset=utf-8
< Content-Length: 3052
< Vary: Accept-Encoding
< Server: gunicorn/19.7.1
< Last-modified: Sun, 25 Aug 2019 16:00:30 GMT
< Cache-Control: public, max-age=43200
< Expires: Mon, 14 Oct 2019 07:36:57 GMT
< ETag: "1566748830.0-3052-3932359948"
La plupart des clients ignorent les dates invalides, ce qui les rend incapables de comprendre la réponse qui leur est servie. Cela peut avoir des conséquences sur la possibilité de mise en cache, puisqu’un en-tête Last-Modified
erroné sera mis en cache sans l’horodatage Last-Modified
, ce qui rendra impossible l’exécution d’une requête conditionnelle.
L’en-tête de réponse HTTP Date
est généralement généré par le serveur web ou le CDN qui sert la réponse à un client. Comme l’en-tête est généralement généré automatiquement par le serveur, il a tendance à être moins sujet aux erreurs, ce qui se reflète dans le très faible pourcentage d’en-têtes Date
invalides. Les en-têtes Last-Modified
sont très similaires, avec seulement 0,67 % d’en-têtes invalides. Ce qui est très surprenant, c’est que 3,64 % des en-têtes Expires
utilisent un format de date invalide !
Voici des exemples d’utilisations incorrectes de l’en-tête Expires
:
- Formats de date valides, mais utilisant un fuseau horaire autre que GMT
- Valeurs numériques telles que 0 ou -1
- Valeurs qui seraient valides dans un en-tête
Cache-Control
La plus grande source d’en-têtes Expires
invalides provient de ressources servies par une tierce partie , dans lesquels un horodatage utilise le fuseau horaire EST, par exemple Expires: Tue, 27 Apr 1971 19:44:06 EST
.
En-tête Vary
L’une des étapes les plus importantes de la mise en cache est de déterminer si la ressource demandée est mise en cache ou non. Bien que cela puisse paraître simple, il arrive souvent que l’URL seule ne suffise pas à le déterminer. Par exemple, les requêtes ayant la même URL peuvent varier en fonction de la compression utilisée (Gzip, Brotli, etc.) ou être modifiées et adaptées aux visiteurs mobiles.
Pour résoudre ce problème, les clients donnent à chaque ressource mise en cache un identifiant unique (une clé de cache). Par défaut, cette clé de cache est simplement l’URL de la ressource, mais les développeurs et développeuses peuvent ajouter d’autres éléments (comme la méthode de compression) en utilisant l’en-tête Vary
.
Un en-têteVary
demande au client d’ajouter la valeur d’une ou plusieurs valeurs d’en-tête de requête à la clé de cache. L’exemple le plus courant est Vary : Accept-Encoding
, qui se traduira par différentes entrées en cache pour les valeurs d’en-tête de requête Accept-Encoding
(c’est-à-dire gzip
, br
, deflate
).
Une autre valeur commune est Vary: Accept-Encoding, User-Agent
, qui demande au client de varier l’entrée en cache à la fois par les valeurs de Accept-Encoding
et par la chaîne User-Agent
. Lorsqu’il s’agit de proxies et de CDN partagés, l’utilisation de valeurs autres que Accept-Encoding
peut être problématique car elle dilue les clés de cache et peut réduire le volume de trafic servi à partir du cache.
En général, vous ne devez modifier le cache que si vous servez un contenu alternatif aux clients en fonction de cet en-tête.
L’en-tête Vary
est utilisé sur 39 % des réponses HTTP, et 45 % des réponses qui incluent un en-tête Cache-Control
.
Le graphique ci-dessous détaille la popularité des 10 premières valeurs d’en-tête Vary
. L’Accept-Encoding
représente 90 % de l’utilisation de Vary
, avec User-Agent
(11 %), Origin
(9 %), et Accept
(3 %) constituant la majeure partie du reste.
L’utilisation de cookies pour la mise en cache des réponses
Lorsqu’une réponse est mise en cache, tous ses en-têtes sont également stockés dans le cache. C’est pourquoi vous pouvez voir les en-têtes de réponse lorsque vous inspectez une réponse mise en cache via DevTools.
Mais que se passe-t-il si vous avez un Set-Cookie
dans une réponse ? Selon la RFC 7234 Section 8, la présence d’un en-tête de réponse Set-Cookie
n’empêche pas la mise en cache. Cela signifie qu’une entrée mise en cache peut contenir un Set-Cookie
si elle a été mise en cache avec. La RFC recommande ensuite que vous configuriez des en-têtes Cache-Control
appropriés pour contrôler la mise en cache des réponses.
L’un des risques de la mise en cache avec Set-Cookie
est que les valeurs des cookies puissent être stockées et servies à des requêtes ultérieures. Suivant l’objectif du cookie, cela pourrait avoir des résultats inquiétants. Par exemple, si un cookie de connexion ou un cookie de session est présent dans un cache partagé, alors ce cookie pourrait être réutilisé par un autre client. Une façon d’éviter cela est d’utiliser la directive Cache-Control
private
, qui permet uniquement la mise en cache de la réponse par le navigateur du client.
3 % des réponses pouvant être mises en cache contiennent un en-tête Set-Cookie
. Parmi ces réponses, seulement 18 % utilisent la directive private
. Les 82 % restants comprennent 5,3 millions de réponses HTTP qui incluent un Set-Cookie
qui peut être mis en cache par des serveurs de cache publics et privés.
AppCache et service workers
L’Application Cache ou AppCache est une fonctionnalité de HTML5 qui permet aux développeurs et développeuses de spécifier les ressources que le navigateur doit mettre en cache et mettre à disposition des utilisateurs hors ligne. Cette fonctionnalité a été dépréciée et supprimée des standards du web, et sa prise en charge par les navigateurs a diminué. En fait, lorsque son utilisation est détectée, Firefox v44+ recommande aux développeurs et développeuses d’utiliser plutôt des service workers. Chrome 70 limite le cache d’application au seul contexte sécurisé. Le secteur s’est davantage orienté vers la mise en œuvre de ce type de fonctionnalité avec des service workers - et la prise en charge des navigateurs a connu une croissance rapide dans ce domaine.
En fait, l’un des rapports de tendance des archives HTTP montre l’adoption des travailleurs des services présenté ci-dessous :
L’adoption est toujours inférieure à 1 % des sites web, mais elle est en constante augmentation depuis janvier 2017. Le chapitre Progressive Web App en parle davantage, notamment du fait qu’ils sont beaucoup plus utilisés que ne le suggère ce graphique en raison de leur utilisation sur des sites populaires, qui ne sont comptés qu’une fois dans le graphique ci-dessus.
Dans le tableau ci-dessous, vous pouvez voir un résumé de l’utilisation d’AppCache par rapport aux service workers. 32 292 sites web ont mis en place un service worker, tandis que 1 867 sites utilisent toujours la fonctionnalité AppCache, qui est obsolète.
N’utilisent pas de Server Worker | Utilisent un Service Worker | Total | |
---|---|---|---|
N’utilise pas AppCache | 5,045,337 | 32,241 | 5,077,578 |
Utilise AppCache | 1,816 | 51 | 1,867 |
Total | 5,047,153 | 32,292 | 5,079,445 |
Si on fait une comparaison entre HTTP et HTTPS, cela devient encore plus intéressant. 581 des sites compatibles avec l’AppCache sont servis en HTTP, ce qui signifie que Chrome a probablement désactivé cette fonctionnalité. Le HTTPS est obligatoire pour l’utilisation des services workers, mais 907 des sites qui les utilisent sont servis en HTTP.
N’utilise pas Service Worker | Utilise Service Worker | ||
---|---|---|---|
HTTP | N’utilise pas AppCache | 1,968,736 | 907 |
Utilise AppCache | 580 | 1 | |
HTTPS | N’utilise pas AppCache | 3,076,601 | 31,334 |
Utilise AppCache | 1,236 | 50 |
Identifier les possibilités de mise en cache
L’outil Lighthouse de Google permet aux utilisateurs d’effectuer une série d’audits sur les pages web, et l’audit de la politique de cache évalue si un site peut bénéficier d’une mise en cache supplémentaire. Pour ce faire, il compare l’âge du contenu (via l’en-tête Last-Modified
) au TTL de la ressource en cache et estime la probabilité que la ressource soit servie à partir du cache. En fonction du score, vous pouvez voir dans les résultats une recommandation de mise en cache, avec une liste de ressources spécifiques qui pourraient être mises en cache.
Lighthouse calcule un score pour chaque audit, allant de 0 à 100 %, et ces scores sont ensuite pris en compte dans les scores globaux. Le score de mise en cache est basé sur les économies potentielles d’octets. En examinant les résultats de Lighthouse, on peut se faire une idée du nombre de sites qui réussissent bien avec leur politique de cache.
Seuls 3,4 % des sites ont obtenu un score de 100 %, ce qui signifie que la plupart des sites peuvent bénéficier de certaines optimisations du cache. La grande majorité des sites ont un score inférieur à 40 %, 38 % ayant un score inférieur à 10 %. En partant de là, on peut affirmer qu’il existe un nombre important d’opportunités de mise en cache sur le web.
Lighthouse indique également combien d’octets pourraient être économisés sur les vues répétées en permettant une politique de cache plus longue. Parmi les sites qui pourraient bénéficier d’une mise en cache supplémentaire, 82 % d’entre eux peuvent réduire le poids de leurs pages jusqu’à un Mo entier !
Conclusion
La mise en cache est une fonction incroyablement puissante qui permet aux navigateurs, aux serveurs de proxy et autres intermédiaires (tels que les CDN) de stocker le contenu du web et de le servir aux utilisateurs finaux. Les avantages en termes de performances sont considérables, puisqu’elle réduit les temps de trajet (aller-retour) et minimise les requêtes coûteuses sur le réseau.
La mise en cache est également un sujet très complexe. Il existe de nombreux en-têtes de réponse HTTP qui peuvent transmettre la fraîcheur ainsi que valider les entrées mises en cache, et les directives Cache-Control
offrent une très grande souplesse et un très grand contrôle. Cependant, les développeurs et développeuses doivent être prudent·e·s quant aux possibilités supplémentaires d’erreurs que ces directives offrent. Il est recommandé de vérifier régulièrement votre site pour s’assurer que les ressources pouvant être mises en cache le sont correctement, et des outils comme Lighthouse et REDbot font un excellent travail pour aider à simplifier l’analyse.