Configurer le comportement de la mise en cache HTTP

Cet atelier de programmation vous explique comment modifier les en-têtes de mise en cache HTTP renvoyés par un serveur Web basé sur Node.js, exécutant le framework de diffusion Express. Vous apprendrez également à vérifier que le comportement de mise en cache attendu est bien appliqué, à l'aide du panneau "Réseau" des outils de développement de Chrome.

Se familiariser avec l'exemple de projet

Voici les fichiers clés que vous allez utiliser dans l'exemple de projet :

  • server.js contient le code Node.js qui diffuse le contenu de l'application Web. Il utilise Express pour gérer les requêtes et les réponses HTTP. En particulier, express.static() est utilisé pour diffuser tous les fichiers locaux du répertoire public. La documentation serve-static vous sera donc utile.
  • public/index.html correspond au code HTML de l'application Web. Comme la plupart des fichiers HTML, il ne contient aucune information sur la version dans son URL.
  • public/app.15261a07.js et public/style.391484cf.css sont les éléments JavaScript et CSS de l'application Web. Chacun de ces fichiers contient un hachage dans son URL, qui correspond à son contenu. Le index.html est chargé de suivre l'URL versionnée spécifique à charger.

Configurer les en-têtes de mise en cache pour notre code HTML

Lorsque vous répondez à des demandes d'URL qui ne contiennent pas d'informations sur le versionnage, assurez-vous d'ajouter Cache-Control: no-cache à vos messages de réponse. Il est également recommandé de définir l'un des deux en-têtes de réponse supplémentaires : Last-Modified ou ETag. Le index.html entre dans cette catégorie. Vous pouvez décomposer cette tâche en deux étapes.

Tout d'abord, les en-têtes Last-Modified et ETag sont contrôlés par les options de configuration etag et lastModified. Ces deux options sont en fait définies par défaut sur true pour toutes les réponses HTTP. Dans la configuration actuelle, vous n'avez donc pas besoin d'activer cette fonctionnalité pour obtenir ce comportement. Toutefois, vous pouvez être explicite dans votre configuration.

Deuxièmement, vous devez pouvoir ajouter l'en-tête Cache-Control: no-cache, mais uniquement pour vos documents HTML (index.html, dans ce cas). Le moyen le plus simple de définir cet en-tête de manière conditionnelle consiste à écrire un setHeaders function personnalisé et, dans celui-ci, à vérifier si la requête entrante concerne un document HTML.

  • Cliquez sur Remix to Edit (Remixer pour modifier) pour rendre le projet modifiable.

La configuration de diffusion statique dans server.js commence comme suit :

app.use(express.static('public'));
  • Apportez les modifications décrites ci-dessus. Vous devriez obtenir un résultat semblable à celui-ci :
app.use(express.static('public', {
  etag: true, // Just being explicit about the default.
  lastModified: true,  // Just being explicit about the default.
  setHeaders: (res, path) => {
    if (path.endsWith('.html')) {
      // All of the project's HTML files end in .html
      res.setHeader('Cache-Control', 'no-cache');
    }
  },
}));

Configurer les en-têtes de mise en cache pour les URL avec version

Lorsque vous répondez à des demandes concernant des URL contenant des informations sur l'empreinte digitale ou le versionnage, et dont le contenu n'est jamais censé changer, ajoutez Cache-Control: max-age=31536000 à vos réponses. app.15261a07.js et style.391484cf.css appartiennent à cette catégorie.

En vous appuyant sur le setHeaders function utilisé à la dernière étape, vous pouvez ajouter une logique supplémentaire pour vérifier si une requête donnée concerne une URL versionnée et, le cas échéant, ajouter l'en-tête Cache-Control: max-age=31536000.

Le moyen le plus fiable consiste à utiliser une expression régulière pour déterminer si le composant demandé correspond à un modèle spécifique dans lequel vous savez que les hachages se trouvent. Dans le cas de cet exemple de projet, il s'agit toujours de huit caractères de l'ensemble des chiffres 0 à 9 et des lettres minuscules a à f (c'est-à-dire des caractères hexadécimaux). Le hachage est toujours séparé par un caractère . de chaque côté.

Une expression régulière qui correspond à ces règles générales peut être exprimée sous la forme new RegExp('\\.[0-9a-f]{8}\\.').

  • Modifiez la fonction setHeaders pour qu'elle se présente comme suit :
app.use(express.static('public', {
  etag: true, // Just being explicit about the default.
  lastModified: true,  // Just being explicit about the default.
  setHeaders: (res, path) => {
    const hashRegExp = new RegExp('\\.[0-9a-f]{8}\\.');

    if (path.endsWith('.html')) {
      // All of the project's HTML files end in .html
      res.setHeader('Cache-Control', 'no-cache');
    } else if (hashRegExp.test(path)) {
      // If the RegExp matched, then we have a versioned URL.
      res.setHeader('Cache-Control', 'max-age=31536000');
    }
  },
}));

Confirmer le nouveau comportement à l'aide des outils pour les développeurs

Une fois les modifications apportées au serveur de fichiers statiques, vous pouvez vérifier que les bons en-têtes sont définis en prévisualisant l'application en direct avec le panneau "Réseau" des outils pour les développeurs ouvert.

  • Personnalisez les colonnes affichées dans le panneau "Réseau" pour inclure les informations les plus pertinentes. Pour ce faire, effectuez un clic droit sur l'en-tête de colonne :

Configurer le panneau "Réseau" des outils de développement.

Ici, les colonnes à examiner sont Name, Status, Cache-Control, ETag et Last-Modified.

  • Une fois les outils de développement ouverts sur le panneau "Réseau", actualisez la page.

Une fois la page chargée, vous devriez voir des entrées dans le panneau "Réseau" qui ressemblent à ce qui suit :

Colonnes du panneau "Réseau".

La première ligne correspond au document HTML vers lequel vous avez accédé. Il est correctement diffusé avec Cache-Control: no-cache. L'état de réponse HTTP pour cette requête est 304. Cela signifie que le navigateur savait qu'il ne devait pas utiliser immédiatement le code HTML mis en cache, mais qu'il devait plutôt envoyer une requête HTTP au serveur Web, en utilisant les informations Last-Modified et ETag pour vérifier si le code HTML qu'il avait déjà dans son cache avait été mis à jour. La réponse HTTP 304 indique qu'il n'y a pas de code HTML mis à jour.

Les deux lignes suivantes concernent les éléments JavaScript et CSS versionnés. Vous devriez les voir diffusées avec Cache-Control: max-age=31536000, et l'état HTTP de chacune est 200. En raison de la configuration utilisée, aucune requête n'est réellement envoyée au serveur Node.js. Si vous cliquez sur l'entrée, des informations supplémentaires s'affichent, y compris le fait que la réponse provient "(du cache disque)".

Un état de réponse réseau de 200.

Les valeurs réelles des colonnes "ETag" et "Last-Modified" n'ont pas beaucoup d'importance. L'important est de confirmer qu'elles sont définies.

En résumé

Après avoir suivi les étapes de cet atelier de programmation, vous savez désormais comment configurer les en-têtes de réponse HTTP dans un serveur Web basé sur Node.js à l'aide d'Express, pour une utilisation optimale du cache HTTP. Vous trouverez également la procédure à suivre pour vérifier que le comportement de mise en cache attendu est utilisé, via le panneau "Réseau" des outils de développement de Chrome.