Москва: проверенные б/у ноутбуки с гарантией и проверкой перед оплатой
+7 906 722-94-45

Главная → Статьи → Service worker: кэширование

Service worker: стратегии кэширования запросов

Кэширование в service worker: стратегии кэша, порядок обращения к сети, версионирование кэша и очистка устаревших записей.

Прямой ответ

Service worker перехватывает запрос и решает, отдать запись из кэша либо обратиться к сети, поэтому стратегия определяет актуальность содержимого.

Стратегия Что выполняется
Только кэш Запись отдаётся из кэша без сети
Сначала сеть Запрос к сети, при отказе — кэш
Сначала кэш Запись из кэша, при отсутствии — сеть
Фон с обновлением Запись из кэша и запрос к сети
self.addEventListener("fetch", (event) => {
  event.respondWith(
    caches.match(event.request).then((hit) => hit || fetch(event.request))
  );
});

Запись из кэша отдаётся при наличии, иначе выполняется запрос к сети, поэтому страница загружается и без соединения. О приложении — в статье про PWA.

Стратегии кэширования и выбор подхода

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

Только кэш. Запись отдаётся из кэша без обращения к сети, поэтому содержимое не обновляется до смены версии кэша.

Сначала сеть. Запрос выполняется к сети, а кэш используется при отказе, поэтому содержимое актуально при доступной сети.

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

Практическое следствие: стратегия «только кэш» для изменяемого содержимого отдаёт прежнее значение до смены версии кэша, поэтому обновление не отражается.

Отдельный аспект — обновление в фоне. Запись отдаётся из кэша немедленно, а запрос к сети обновляет кэш, поэтому следующее открытие показывает актуальное содержимое.

Версионирование кэша и область записей

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

Имя кэша с версией. Имя содержит версию, поэтому изменение версии создаёт новый набор записей.

Набор записей версии. Записи добавляются в кэш текущей версии, поэтому прежние записи остаются в кэше прежней версии.

Область кэширования. Типы запросов, помещаемые в кэш, определяются явно, поэтому кэш не заполняется посторонними записями.

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

Очистка устаревших кэшей и активация

Устаревшие кэши удаляются при активации новой версии, поэтому объём хранилища не растёт с каждой сборкой.

Удаление прежних версий. Кэши с именами, не соответствующими текущей версии, удаляются при активации, поэтому объём хранилища освобождается.

Момент удаления. Удаление выполняется после активации новой версии, поэтому открытые страницы прежней версии не теряют записи.

Ограничение объёма. Число записей в кэше ограничивается, поэтому объём хранилища не превышает допустимый.

Практическое следствие: отсутствие удаления прежних версий приводит к накоплению записей, поэтому объём хранилища растёт с каждой сборкой.

Об автономной работе — в статье про офлайн-режим; о заголовках кэша — в статье про HTTP-кэширование.

Практика: настройка кэширования в service worker

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

2. Используйте обновление в фоне для часто открываемых страниц. Запись отдаётся немедленно, а кэш обновляется запросом к сети.

3. Включайте версию в имя кэша. Смена версии отделяет новые записи от прежних.

4. Ограничивайте область кэшируемыми типами запросов. Кэш не заполняется посторонними записями.

5. Удаляйте кэши прежних версий при активации. Объём хранилища освобождается после обновления.

6. Ограничивайте число записей в кэше. Объём хранилища не превышает допустимый.

7. Проверяйте загрузку без соединения. Работа без сети подтверждается проверкой, а не наличием кэша.

Рекомендации:

  1. Не кэшируйте изменяемое содержимое стратегией «только кэш». Прежнее значение отдаётся до смены версии кэша.
  2. Учитывайте момент удаления прежних версий. Открытые страницы прежней версии не должны терять записи.
  3. Сопоставляйте стратегию с типом содержимого. Статические файлы и данные запросов требуют разного порядка обращения.
  4. Фиксируйте проверку автономной загрузки в процессе разработки. Отсутствие записей в кэше обнаруживается до выпуска.
  5. Пересматриваем набор кэшируемых ресурсов при изменении сборки. Новый ресурс требует включения в предварительный кэш.

Практический сценарий: после обновления пользователи видели прежнюю версию

Контекст: новая сборка была выпущена, но часть пользователей продолжала видеть прежний интерфейс в течение длительного времени.

  1. Диагностика. Проверка показала, что имя кэша не содержало версии, поэтому записи прежней сборки продолжали отдаваться. Обработчик отдавал запись из кэша при её наличии и не обращался к сети.
  2. Причина. Отсутствие версионирования кэша приводило к тому, что устаревшие файлы оставались в том же наборе записей и отдавались вместо новых.
  3. Действия. (а) Добавили версию в имя кэша, чтобы смена сборки создавала новый набор записей; (б) настроили удаление кэшей прежних версий при активации обработчика, чтобы объём хранилища освобождался; (в) применили стратегию с обновлением в фоне для страницы приложения, чтобы актуальная версия загружалась при следующем открытии; (г) ограничили число записей в кэше, чтобы объём хранилища не рос; (д) проверили загрузку после обновления и убедились в отдаче новой версии.
  4. Результат. После обновления пользователи получают новую версию, поскольку кэш разделяется по версиям и прежние записи удаляются.

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

FAQ

Какую стратегию кэширования выбрать для статических файлов? Стратегию «только кэш» либо «сначала кэш». Содержимое не изменяется между сборками, поэтому обращение к сети не требуется.

Почему важно включать версию в имя кэша? Смена версии создаёт новый набор записей, поэтому устаревшие файлы прежней сборки не отдаются после обновления.

Когда удаляются кэши прежних версий? При активации новой версии обработчика. Открытые страницы прежней версии не теряют записи до закрытия.

Что даёт обновление кэша в фоне? Запись отдаётся из кэша немедленно, а запрос к сети обновляет кэш, поэтому следующее открытие показывает актуальное содержимое.

Источники: W3C Service Workers, web.dev Cache Storage, RFC 9111 HTTP Caching — ссылки в шапке.