Определение изменённых заголовков

Workbox предоставляет мощные инструменты для работы с кэшированием ресурсов и управлением стратегиями Service Worker. Одной из ключевых задач при обновлении ресурсов является определение изменённых заголовков, что позволяет эффективно контролировать актуальность кэша и минимизировать лишние сетевые запросы.

Использование cacheWillUpdate для проверки заголовков

В Workbox каждый маршрут может быть настроен с кастомной стратегией кэширования. Метод cacheWillUpdate позволяет определить, какой ответ должен быть сохранён в кэше. Основное применение — проверка заголовков ответа, например ETag или Last-Modified.

import {CacheFirst} from 'workbox-strategies';
import {registerRoute} from 'workbox-routing';

registerRoute(
  ({request}) => request.destination === 'script',
  new CacheFirst({
    cacheName: 'js-cache',
    plugins: [
      {
        cacheWillUpdate: async ({request, response, event, state}) => {
          // Проверка наличия заголовка ETag
          const etag = response.headers.get('ETag');
          if (!etag) return null;

          // Логика определения обновления ресурса
          const cachedResponse = await caches.match(request);
          if (cachedResponse) {
            const cachedEtag = cachedResponse.headers.get('ETag');
            if (cachedEtag === etag) {
              // Если ETag совпадает, не обновляем кэш
              return null;
            }
          }

          // Возвращаем ответ для кэширования
          return response;
        }
      }
    ]
  })
);

Ключевой момент: cacheWillUpdate вызывается перед записью ответа в кэш. Возвращение null предотвращает перезапись устаревшего ресурса.

Сравнение заголовков ETag и Last-Modified

  • ETag — уникальный идентификатор версии ресурса. Подходит для точной проверки изменений.
  • Last-Modified — дата последнего изменения. Может быть менее точным, если сервер не обновляет её корректно.

Для большинства проектов рекомендуется использовать ETag как основной индикатор обновлений.

const isResourceModified = (cachedResponse, newResponse) => {
  const cachedEtag = cachedResponse?.headers.get('ETag');
  const newEtag = newResponse.headers.get('ETag');

  if (!cachedEtag || !newEtag) return true;
  return cachedEtag !== newEtag;
};

Интеграция с стратегиями Workbox

Workbox поддерживает различные стратегии кэширования: CacheFirst, NetworkFirst, StaleWhileRevalidate. Проверка изменённых заголовков особенно важна для стратегий CacheFirst и StaleWhileRevalidate, где ресурс может оставаться в кэше длительное время.

Пример интеграции с StaleWhileRevalidate:

import {StaleWhileRevalidate} from 'workbox-strategies';

registerRoute(
  ({request}) => request.destination === 'image',
  new StaleWhileRevalidate({
    cacheName: 'image-cache',
    plugins: [
      {
        cacheWillUpdate: async ({request, response}) => {
          const cachedResponse = await caches.match(request);
          if (cachedResponse && !isResourceModified(cachedResponse, response)) {
            return null;
          }
          return response;
        }
      }
    ]
  })
);

Использование Workbox ExpirationPlugin и заголовков

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

import {ExpirationPlugin} from 'workbox-expiration';

new StaleWhileRevalidate({
  cacheName: 'api-cache',
  plugins: [
    new ExpirationPlugin({
      maxEntries: 50,
      maxAgeSeconds: 24 * 60 * 60
    }),
    {
      cacheWillUpdate: async ({request, response}) => {
        const cachedResponse = await caches.match(request);
        if (cachedResponse && !isResourceModified(cachedResponse, response)) {
          return null;
        }
        return response;
      }
    }
  ]
});

Практические рекомендации

  1. Всегда проверять наличие ETag перед сравнением.
  2. Использовать cacheWillUpdate для тонкого контроля обновлений.
  3. Для критичных ресурсов применять стратегию NetworkFirst с проверкой заголовков.
  4. Комбинировать ExpirationPlugin с заголовками для автоматической очистки устаревших данных.
  5. Логировать изменения заголовков при отладке кэша для выявления проблем с версионированием.

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