В предыдущем разделе Правильно кешировать: основные вопросы интервью с фронтендом по HTTP-кэшированию — часть 1 мы обсуждали:

  • Основные понятия кэширования
  • Преимущества использования кэширования в веб-приложениях
  • Общий код состояния ответа http для кэшированных ресурсов
  • Некоторые часто запрашиваемые заголовки http для кэширования

В сегодняшней статье мы покажем некоторые общие настройки кэша, о которых вам необходимо знать для различных типов ресурсов и сценариев.

По умолчанию: эвристическое кэширование.

Эвристическое кэширование — это обходной путь, появившийся до того, как поддержка Cache-Control стала широко распространенной, и в основном все ответы должны явно указывать заголовок Cache-Control.

Date: Wed, 23 Feb 2023 00:00:00 GMT
Last-Modified: Wed, 23 Feb 2023 00:00:00 GMT

В этом примере, даже если Cache-Control не указано, ответы будут сохранены и повторно использованы при соблюдении определенных условий. Это называется эвристическим кэшированием (поскольку HTTP предназначен для максимально возможного кэширования).

Клиент сохраняет этот ответ (несмотря на отсутствие max-age) и какое-то время повторно использует его.

Пример использования: долгоживущее кэширование для версионированных URL-адресов.

Cache-Control: max-age=31536000

Этот параметр также подходит для неизменяемых ресурсов. (например, ваши версии JavaScript, CSS, изображений).

В современной веб-разработке ресурсы JavaScript и CSS часто обновляются по ходу разработки. Кроме того, если версии ресурсов JavaScript и CSS, которые использует клиент, не синхронизированы, отображение сломается.

Таким образом, вы можете использовать JavaScript и CSS с URL-адресами, которые включают изменяющуюся часть на основе номера версии или хеш-значения.

При ответе на запросы URL-адресов, содержащих информацию о версиях, если содержимое никогда не должно меняться, добавляйте Cache-Control: max-age=31536000 к своим ответам.

# version in filename
bundle-v111.js
# version in query param
bundle.js?v=111
# hash in filename
bundle-md5hashvalue.js
# hash in query
bundle.js?v=md5hashvalue

Установка этого значения сообщает браузеру, что всякий раз, когда ему нужно загрузить один и тот же URL-адрес в любое время в течение следующего года (31 536 000 секунд), он может немедленно использовать значение в HTTP-кэше, вообще не делая сетевой запрос к вашему веб-серверу. .

Например, в AWS, когда вы вносите изменения в кодовую базу внешнего интерфейса, это обычно включает в себя развертывание нового версионного пакета JavaScript. Вы можете увидеть заголовок cache-control на скриншоте ниже.

Инструменты сборки, такие как webpack, могут автоматизировать процесс назначения хэш-отпечатков URL-адресам ваших активов.

Вы также можете добавить свойство immutable в заголовок Cache-Control для дальнейшей оптимизации, хотя в некоторых браузерах оно будет игнорироваться.

Вариант использования: когда вы не хотите делиться ресурсом с другими

Если ответ содержит персонализированный контент, и вы не хотите, чтобы этот контент был неожиданно виден другим, добавьте директиву private в заголовок Cache-Control.

Cache-Control: private

В этом случае использование директивы private приведет к тому, что персонализированный ответ будет храниться только у конкретного клиента и не будет передан другому пользователю кэша.

Вариант использования: когда вы хотите предоставлять актуальный контент каждый раз

У вас может возникнуть соблазн использовать директиву no-store. Директива no-store предотвращает сохранение ответа, но не удаляет уже сохраненный ответ для того же URL.

Если для определенного URL-адреса уже сохранен старый ответ, возврат no-store не предотвратит повторное использование старого ответа.

Однако директива no-cache заставит клиента отправить запрос на проверку перед повторным использованием любого сохраненного ответа.

Cache-Control: no-cache, no-store

В этом шаблоне вы также можете добавить к ответу заголовок даты ETag (идентификатор версии по вашему выбору) или Last-Modified. В следующий раз, когда клиент извлекает ресурс, он повторяет значение уже имеющегося у него контента через If-None-Match и If-Modified-Since соответственно, позволяя серверу сказать: «Просто используйте то, что у вас уже есть, оно обновлено» или как пишется. , 'HTTP 304'.

Пример использования: используйте сервис-воркер для обслуживания офлайн-контента.

Это отличная статья о том, как настроить сервис-воркера и его настройки кеша:

Лучшие практики кэширования и ошибки максимального возраста — JakeArchibald.com

Суммируя

self.addEventListener('install', (event) => {
  event.waitUntil(
    caches
      .open(`static-${version}`)
      .then((cache) =>
        cache.addAll([
          '/root.html',
          '/script-v123.js',
          '/styles-v234.css',
          '/img-v123.jpg',
        ]),
      ),
  );
});

Для корневой html-страницы ее заголовок Cache-Controle должен иметь значение

Cache-Control: no-cache

так что каждое обновление сервисного работника инициирует запрос на корневую страницу. но остальные ресурсы:

'/script-v123.js',
'/styles-v234.css',
'/img-v123.jpg',

будет иметь этот параметр Cache-Control:

Cache-Control: max-age=31536000

Они будут загружены только в том случае, если их URL изменился.