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 service Express. Il vous montrera également comment vérifier que le comportement de mise en cache attendu est effectivement appliqué à l'aide du panneau "Network" (Réseau) de DevTools dans Chrome.

Se familiariser avec l'exemple de projet

Voici les fichiers de 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 sur 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 de gestion des versions 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 ses URL, correspondant à 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 requêtes d'URL qui ne contiennent pas d'informations de gestion des versions, veillez à ajouter Cache-Control: no-cache à vos messages de réponse. En outre, il est recommandé de définir l'un des deux en-têtes de réponse supplémentaires: Last-Modified ou ETag. index.html entre dans cette catégorie. Vous pouvez décomposer cette opération 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 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 ce comportement. Vous pouvez toutefois ê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é, puis à vérifier si la requête entrante concerne un document HTML.

  • Cliquez sur 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 quelque chose qui ressemble à ceci:
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 des en-têtes de mise en cache pour les URL avec version

Lorsque vous répondez à des requêtes d'URL contenant un "empreinte" ou des informations de gestion des versions, et dont le contenu ne doit jamais changer, ajoutez Cache-Control: max-age=31536000 à vos réponses. app.15261a07.js et style.391484cf.css font partie de cette catégorie.

En partant de l'setHeaders function utilisé à l'étape précédente, vous pouvez ajouter une logique supplémentaire pour vérifier si une requête donnée concerne une URL versionnée, et si oui, ajouter l'en-tête Cache-Control: max-age=31536000.

Le moyen le plus robuste d'y parvenir consiste à utiliser une expression régulière pour vérifier si l'élément demandé correspond à un modèle spécifique que vous savez que les hachages entrent dans. Dans le cas de cet exemple de projet, il s'agit toujours de huit caractères de l'ensemble des chiffres de 0 à 9 et des lettres minuscules de 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');
    }
  },
}));

Vérifier le nouveau comportement à l'aide de DevTools

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.

  • Pour prévisualiser le site, appuyez sur Afficher l'application, puis sur Plein écran plein écran.

  • Pour personnaliser les colonnes affichées dans le panneau "Réseau" afin d'inclure les informations les plus pertinentes, cliquez avec le bouton droit de la souris sur l'en-tête de colonne:

Configuration du panneau "Network" (Réseau) de DevTools.

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

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

Une fois la page chargée, des entrées semblables aux suivantes doivent s'afficher dans le panneau "Network" (Réseau) :

Colonnes du panneau réseau.

La première ligne correspond au document HTML auquel vous avez accédé. Cela est correctement servi avec Cache-Control: no-cache. L'état de réponse HTTP de cette requête est 304. Cela signifie que le navigateur savait ne pas utiliser le code HTML mis en cache immédiatement, mais a plutôt envoyé une requête HTTP au serveur Web, à l'aide des informations Last-Modified et ETag pour voir s'il y avait une mise à jour du code HTML qu'il avait déjà dans son cache. La réponse HTTP 304 indique qu'il n'y a pas de code HTML mis à jour.

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

État de réponse réseau : 200.

Les valeurs réelles des colonnes "ETag" et "Last-Modified" n'ont pas beaucoup d'importance. L'essentiel est de vérifier qu'ils sont définis.

Récapitulatif

Après avoir suivi les étapes de cet atelier de programmation, vous savez maintenant 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 "Network" (Réseau) des outils de développement de Chrome.