Настройка поведения HTTP-кэширования

В этой лабораторной работе показано, как изменить HTTP-заголовки кэширования, возвращаемые веб-сервером на базе Node.js, работающим под управлением фреймворка Express . Также будет показано, как убедиться в том, что ожидаемое поведение кэширования действительно применяется, с помощью панели «Сеть» в инструментах разработчика Chrome.

Ознакомьтесь с примером проекта

Вот ключевые файлы, с которыми вы будете работать в примере проекта:

  • server.js содержит код Node.js, обслуживающий контент веб-приложения. Он использует Express для обработки HTTP-запросов и ответов. В частности, express.static() используется для обслуживания всех локальных файлов в каталоге public, поэтому документация serve-static будет вам полезна.
  • public/index.html — это HTML-код веб-приложения. Как и большинство HTML-файлов, он не содержит информации о версии в URL-адресе.
  • public/app.15261a07.js и public/style.391484cf.css — это ресурсы JavaScript и CSS веб-приложения. Каждый из этих файлов содержит хэш в URL-адресе, соответствующий их содержимому. Файл index.html отвечает за отслеживание конкретной версии URL-адреса для загрузки.

Настройте заголовки кэширования для нашего HTML

При ответе на запросы URL, не содержащих информацию о версии, обязательно добавьте Cache-Control: no-cache в свои ответные сообщения. Кроме того, рекомендуется установить один из двух дополнительных заголовков ответа: Last-Modified или ETag . Файл index.html относится к этой категории. Этот процесс можно разбить на два этапа.

Во-первых, заголовки Last-Modified и ETag управляются параметрами конфигурации etag и lastModified . Оба этих параметра по умолчанию установлены в true для всех HTTP-ответов, поэтому в текущей конфигурации вам не нужно включать это поведение. Но вы можете явно указать его в конфигурации.

Во-вторых, вам необходимо иметь возможность добавить заголовок Cache-Control: no-cache , но только для HTML-документов (в данном случае index.html ). Самый простой способ условно установить этот заголовок — написать собственную setHeaders function и в ней проверять, относится ли входящий запрос к HTML-документу.

  • Нажмите «Ремикс для редактирования», чтобы сделать проект редактируемым.

Статическая конфигурация обслуживания в server.js начинается так:

app.use(express.static('public'));
  • Внесите описанные выше изменения, и у вас должно получиться что-то вроде этого:
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');
    }
  },
}));

Настройте заголовки кэширования для версионированных URL-адресов

При ответе на запросы URL, содержащие « отпечаток » или информацию о версии, содержимое которых никогда не должно меняться, добавляйте в свои ответы Cache-Control: max-age=31536000 . Файлы app.15261a07.js и style.391484cf.css относятся к этой категории.

Используя setHeaders function , использованную на последнем шаге, вы можете добавить дополнительную логику для проверки того, относится ли данный запрос к URL-адресу с версией, и если да, добавить заголовок Cache-Control: max-age=31536000 .

Самый надёжный способ сделать это — использовать регулярное выражение , чтобы проверить, соответствует ли запрашиваемый ресурс определённому шаблону, которому, как вам известно, соответствуют хэши. В случае этого проекта это всегда восемь символов из набора цифр 0–9 и строчных букв a–f (т.е. шестнадцатеричных символов). Хеш всегда разделён символом . с обеих сторон.

Регулярное выражение, соответствующее этим общим правилам, можно выразить как new RegExp('\\.[0-9a-f]{8}\\.') .

  • Измените функцию setHeaders так, чтобы она выглядела так:
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');
    }
  },
}));

Подтвердите новое поведение с помощью DevTools

После внесения изменений в статический файловый сервер вы можете проверить, установлены ли правильные заголовки, просматривая работающее приложение с открытой панелью DevTools Network.

  • Настройте столбцы, отображаемые на панели «Сеть», чтобы включить в них наиболее релевантную информацию, щелкнув правой кнопкой мыши заголовок столбца:

Настройка панели «Сеть» DevTools.

Здесь следует обратить внимание на столбцы Name , Status , Cache-Control , ETag и Last-Modified .

  • Открыв DevTools на панели «Сеть», обновите страницу.

После загрузки страницы вы должны увидеть записи на панели «Сеть», которые выглядят следующим образом:

Столбцы сетевой панели.

Первая строка относится к HTML-документу, на который вы перешли. Он корректно обслуживается с помощью Cache-Control: no-cache . HTTP-ответ на этот запрос — 304 . Это означает, что браузер знал, что не следует сразу использовать кэшированный HTML, и вместо этого отправил HTTP-запрос к веб-серверу, используя информацию Last-Modified и ETag , чтобы проверить, были ли какие-либо обновления HTML-документа, уже находившегося в кэше. HTTP-ответ 304 означает, что HTML-документ не обновлён.

Следующие две строки содержат версионированные ресурсы JavaScript и CSS. Вы увидите, что они обслуживаются с помощью Cache-Control: max-age=31536000 , а HTTP-статус для каждого — 200 . Из-за используемой конфигурации фактический запрос к серверу Node.js не отправляется, и при нажатии на запись вы увидите дополнительную информацию, в том числе, что ответ получен «(из дискового кэша)».

Статус ответа сети: 200.

Фактические значения столбцов ETag и Last-Modified не имеют большого значения. Важно убедиться, что они устанавливаются.

Подводя итоги

Выполнив шаги, описанные в этой лабораторной работе, вы теперь знаете, как настроить заголовки HTTP-ответа на веб-сервере на базе Node.js с помощью Express для оптимального использования HTTP-кеша. Вы также знаете, как убедиться в использовании ожидаемого поведения кэширования через панель «Сеть» в инструментах разработчика Chrome.