Mise en cache

Introduction

La mise en cache permet de conserver une copie des données reçues afin d'éviter d'avoir à les solliciter à nouveau.

La plupart des navigateurs Web ont recours à la mise en cache pour conserver une copie des pages Web et des fichiers téléchargés. Etant donné que les informations présentées sur Internet évoluent au fil du temps, chaque navigateur s'en reporte au serveur Web et au concepteur du site pour évaluer la durée pendant laquelle les pages mises en cache devront être conservées. Pour ce faire, il analyse les en-têtes HTTP envoyées par le serveur.

Lorsqu'elle est correctement mise en œuvre, la mise en cache permet de réduire la quantité de bande passante consommée par les utilisateurs, et ce particulièrement pour les utilisateurs qui visitent régulièrement le site concerné.

Recommandations

Utilisez du contenu statique plutôt que dynamique

Les ressources qui contiennent des données statiques sont transmises directement à partir des fichiers présents sur le disque plutôt que par le biais de scripts. Le serveur peut donc facilement communiquer la date à laquelle le contenu statique a été mis à jour pour la dernière fois au navigateur, ce qui permet à ce dernier de ne télécharger une nouvelle copie des données que si le contenu a été modifié.

Définissez et vérifiez la date de la dernière modification dans les scripts

Le serveur ne dispose pas de telles informations pour le contenu dynamique (les données peuvent changer sans que le fichier de script n'en fasse état), ce qui signifie qu'il doit toujours faire appel au script pour générer le contenu.

Il est toutefois possible que votre script soit en mesure d'indiquer au navigateur s'il dispose déjà des informations mises à jour en comparant les en-têtes de demande aux fichiers locaux et aux bases de données utilisés pour générer la réponse.

Définissez l'en-tête Expires pour tous les objets

L'en-tête Expires indique la date après laquelle le contenu auquel il se renvoie sera considéré comme obsolète. Si vous connaissez la date approximative à laquelle votre contenu sera modifié, vous pouvez utiliser l'en-tête Expires pour améliorer l'efficacité du cache des navigateurs ainsi que la rapidité de chargement de vos pages.

Malheureusement, il n'est pas toujours possible de savoir à l'avance à quel moment un contenu sera modifié mais même en cas de doute, il est recommandé de toujours définir l'en-tête Expires.

Si le contenu expire avant d'avoir été modifié, il pourra toujours être téléchargé à nouveau, quand bien même cela entraînerait un certain gaspillage de la bande passante. En revanche, si le contenu expire trop tard, les modifications que vous avez apportées à vos pages ne seront probablement pas mises en œuvre tant que le contenu mis en cache n'aura pas expiré. Il est donc important que vous preniez ces facteurs en compte avant de définir la date d'expiration de votre contenu.

Fonctionnement de la mise en cache

Les navigateurs localisent les informations par le biais de leur adresse URL (Uniform Resource Locater). Chaque ressource (page HTML, image, etc.) est associée à une adresse URL unique. Si une information (page HTML ou image) est accessible par le biais de plusieurs URL, elle sera alors considérée comme plusieurs ressources distinctes. Cela est dû au fait que les navigateurs sont incapables de comparer les informations associées à chaque URL.

Les navigateurs obtiennent les ressources auprès du serveur en envoyant une demande à celui-ci. La demande contient l'URL à extraire ainsi que des en-têtes HTTP de demande dont le but est de fournir des informations supplémentaires sur la demande. Le serveur répond à la demande en envoyant les données de la ressource ainsi que des en-têtes HTTP de réponse. Les en-têtes HTTP de réponse fournissent des informations sur la réponse ou sur les informations qu'elle contient.

Les navigateurs Web sont régulièrement amenés à solliciter des ressources pour répondre aux opérations des utilisateurs, notamment pour charger et afficher des pages Web. Cet échange d'informations entre le navigateur et le serveur se produit lorsque l'utilisateur clique sur un lien qui pointe vers une ressource (un lien hypertexte dans une page Web, par exemple) ou saisit l'adresse d'une ressource dans la barre d'adresse. Il peut également se produire lorsqu'une ressource est référencée dans une page Web et que le navigateur entreprend d'afficher celle-ci dans la page (par exemple, une image ou une feuile de style référencée dans une page HTML, lorsque le navigateur prend en charge ces fonctionnalités).

Bien que les ressources puissent adopter différents types de format (HTML, CSS, JavaScript, JPEG, GIF, PNG, etc.), elles sont toutes mises en cache et récupérées de la même manière, c'est-à-dire sous forme de bloc (fichier) de données binaires.

Lorsqu'un navigateur nécessite une ressource, il consulte son cache (sur le disque local ou dans la mémoire) pour vérifier s'il contient déjà une copie de la ressource et si cette copie n'a pas déjà expiré. Les trois résultats possibles sont les suivants :

Le navigateur contient une copie valable.
Inutile de solliciter la ressource auprès du serveur.
Le navigateur contient une copie locale à laquelle aucune date d'expiration n'est associée.
Demander au serveur d'envoyer une nouvelle copie de la ressource au cas où celle-ci aurait été modifiée depuis son téléchargement.
Le navigateur ne contient aucune copie de la ressource ou la copie qu'il contient a expiré.
Télécharger une nouvelle copie de la ressource à partir du serveur.

La bande passante n'est pas utilisée dans le premier cas de figure et, à moins que la ressource n'ait été modifiée, une quantité moins importante de bande passante est utilisée dans le deuxième cas de figure par rapport au troisième cas de figure.

Le premier cas de figure est également le plus rapide à traiter (aucun échange n'a lieu avec le serveur). Le second cas de figure nécessite au moins deux échanges avec le serveur (généralement quatre) et si le serveur renvoie des données, des échanges et des délais supplémentaires seront nécessaires.

Lorsque le navigateur contient déjà le contenu sollicité, le comportement adopté dépend des informations associées aux en-têtes de réponse suivants :

  • l'en-tête Last-Modified, qui indique la date à laquelle le contenu a été modifié pour la dernière fois ;
  • l'en-tête Expires, qui indique la date à laquelle le contenu expirera et devra être de nouveau extrait.

Lorsque le navigateur (ou un proxy) met en cache la réponse, la date de la dernière modification et la date d'expiration sont enregistrées en même temps que la ressource. Chaque fois que la ressource est de nouveau sollicitée, le navigateur consulte la date d'expiration (si elle est définie) pour vérifier si le contenu mis en cache a expiré. Si aucune date d'expiration n'a été définie, il renvoie la date générée au serveur dans un en-tête de demande et attend que le serveur décide si une nouvelle version du contenu ou une réponse 304 Not Modified (aucune modification apportée) doit être envoyée.

Définition de l'en-tête Last-Modified

Le système de fichiers du serveur effectue un suivi des modifications qui sont apportées aux fichiers. Pour les fichiers statiques, le serveur associe la date à laquelle chaque fichier a été modifié à l'en-tête Last-Modified afin de pouvoir la consulter lorsqu'il reçoit une demande contenant un en-tête If-Modified-Since. De cette manière, il peut vérifier si la date de la dernière modification est ultérieure à la date spécifiée dans la demande. Si la date de la dernière modification est antérieure à la date de la demande, le serveur Web envoie une réponse 304 Not Modified pour indiquer au client qu'il dispose déjà de la dernière version du contenu.

Comme nous l'avons déjà expliqué, l'en-tête Last-Modified peut également être défini par un script. Dans ce cas, c'est le script plutôt que le serveur qui décide si une nouvelle version du contenu ou une réponse 304 Not Modified doit être envoyée.

Pour que ce procédé fonctionne, votre script doit envoyer un en-tête Last-Modified avec chaque réponse pour que celui-ci puisse être mis en cache par le navigateur.
(Exemple)

Définition de l'en-tête Expires

Les recommandations de Microsoft sont les suivantes :

Tous les serveurs Web doivent appliquer une date d'expiration à toutes les pages Web. Tout serveur Web qui ne fournira pas des informations d'expiration par le biais de l'en-tête HTTP de réponse Expires pour toutes les ressources renvoyées aux clients ira à l'encontre des pratiques recommandées. La plupart des navigateurs et des proxy intermédiaires fournissent ces informations d'expiration et contribuent ainsi à améliorer l'efficacité des communications sur le réseau...

Toute page peu susceptible d'être modifiée doit être associée à un délai d'expiration d'environ un an.[1]

Vous devez définir la date à laquelle l'en-tête Expires devra être associé. Par défaut, les serveurs Web n'envoient aucun en-tête Expires car ils ne sont pas en mesure de deviner par eux-mêmes la durée de validité des contenus. Assurez-vous que vous fournissez les informations suivantes :

Les scripts sont en mesure de définir l'en-tête Expires.
(Exemple)

Pour appliquer une date d'expiration à un contenu statique, vous devez configurer le serveur Web de la manière suivante :

  • Sur les serveurs Apache, vous devez activer et configurer le module mod_expires[2]pour fournir des informations sur la date d'expiration qui s'applique à vos fichiers au serveur.
    (Exemple)
  • Sur les serveurs Microsoft IIS, vous devez utiliser le Gestionnaire de services Internet pour configurer la date d'expiration de vos contenus statiques.
    (Exemple)

Exemple d'utilisation de l'en-tête Expires

Si vous mettez à jour votre site Web à 9h chaque matin, vous pouvez définir l'en-tête Expires sur 9h le lendemain :

Expires: Wed, 01 Aug 2007 09:00:00 GMT

Notez qu'en cas de retard (si vous mettez à jour votre site à 9h15 par exemple), les utilisateurs qui accèderont à votre site avant sa mise à jour (entre 9h et 9h15) recevront une copie expirée de chaque page. Même s'ils se rendent à nouveau sur votre site plus tard dans la journée, ils ne pourront pas afficher la version mise à jour de votre site à moins de cliquer sur le bouton d'actualisation de leur navigateur.

Pour éviter qu'un tel problème ne se produise, vous pouvez définir une fenêtre de mise à jour prévue pour s'afficher à 9h pendant une heure en lui associant 10h comme heure d'expiration. Il vous suffit alors de définir l'heure d'expiration de votre site sur l'heure de début de la prochaine fenêtre de mise à jour.

Si vous n'avez pas l'intention de mettre à jour votre site de façon quotidienne, il vous faudra établir une estimation du délai de mise à jour de chaque élément de votre site et définir l'heure d'expiration de ceux-ci en fonction de ce délai.

Si vous savez qu'un élément particulier sera mis à jour à une date particulière, définissez la date d'expiration sur cette date.

Utilisation de l'en-tête Cache-Control

Désactivation de la mise en cache

L'en-tête Cache-Control vous permet de désactiver la mise en cache de manière simple et efficace. Par exemple, chacun des en-têtes suivants permet de désactiver la mise en cache :

Pragma: no-cache
Cache-Control: no-cache
Cache-Control: max-age=0 (or negative)

L'en-tête Pragma: no-cache est une ancienne version de l'en-tête Cache-Control: no-cache prise en charge par les navigateurs HTTP/1.0. Si vous devez envoyer l'un de ces en-têtes, envoyez-les tous deux ou n'en envoyez aucun.

Il est déconseillé d'utiliser ces en-têtes car ils présupposent que vos utilisateurs souhaitent charger le contenu statique de votre site à chaque utilisation et entraînent donc des délais de chargement inutiles si tel n'est pas le cas (si votre site ne change qu'occasionnellement).

Certains systèmes de gestion du contenu (CMS) et certains Wiki génèrent automatiquement des en-têtes Cache-Control. Si une ligne Cache-Control apparaît dans la source de l'une de vos pages, cela signifie que cette page ne sera pas mise en cache.

Désactivation de la mise en cache du contenu privé

Si vous ne souhaitez pas qu'une page soit mise en cache par un cache de proxy intermédiaire (si elle contient des informations personnelles, par exemple), vous pouvez utiliser l'en-tête suivant :

Cache-Control: private

Plutôt que de désactiver l'ensemble de la mise en cache, cet en-tête permet aux informations d'être mises en cache dans le navigateur uniquement.

En outre, il est recommandé de minimiser le nombre de pages contenant des informations personnelles de façon à optimiser la mise en cache de votre site.

En-tête Auto-Refresh

Vous pouvez configurer vos pages de manière à ce qu'elles s'actualisent de façon automatique à l'aide de l'en-tête suivant :

Refresh: 0

ou du métaélément suivant :

<meta http-equiv="refresh" content="0">

Il est déconseillé d'utiliser cet en-tête car il occasionne généralement des pertes de bande passante considérables, aussi bien pour vous que pour vos utilisateurs. Si vous le souhaitez, vous pouvez ajouter une fonctionnalité d'actualisation automatique à votre site pour que vos utilisateurs soient libres de choisir s'ils veulent la mettre en œuvre ou non.

Remarques

Un cache Web peut uniquement conserver des ressources complètes et non pas des ressources partielles.

Pour fournir les en-têtes nécessaires à la mise en cache, vous devez pouvoir définir des en-têtes HTTP arbitraires. Il est important que vous vérifiiez que vous êtes en mesure d'effectuer une telle opération si vous utilisez un fournisseur d'accès à Internet ou un serveur externe.

Synthèse

  • Utilisez du contenu statique dans la mesure du possible
  • Définissez des en-têtes Last-Modified et Expires pour l'ensemble du contenu
  • Evitez d'utiliser les en-têtes Cache-Control et Auto-Refresh

Ressources supplémentaires et didacticiels

Références

[#1] http://support.microsoft.com/kb/234067

[#2] http://httpd.apache.org/docs/1.3/mod/mod_expires.html