Фильтрация по заголовкам ответа

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


Использование CacheableResponsePlugin

Основной инструмент для фильтрации ответов по заголовкам — это плагин CacheableResponsePlugin. Он позволяет задавать условия, при которых ответ будет считаться пригодным для кэширования, на основе HTTP-статуса или заголовков.

Пример подключения и настройки плагина:

import { registerRoute } from 'workbox-routing';
import { StaleWhileRevalidate } from 'workbox-strategies';
import { CacheableResponsePlugin } from 'workbox-cacheable-response';

registerRoute(
  ({request}) => request.destination === 'image',
  new StaleWhileRevalidate({
    cacheName: 'images-cache',
    plugins: [
      new CacheableResponsePlugin({
        statuses: [0, 200],  // только ответы с HTTP 0 (opaque) и 200
        headers: {
          'X-Cacheable': 'true'  // фильтрация по пользовательскому заголовку
        }
      })
    ],
  })
);

Ключевые моменты настройки:

  • statuses: массив разрешённых кодов HTTP-ответа. Только ответы с указанными статусами попадут в кэш.
  • headers: объект, где ключ — имя заголовка, а значение — ожидаемое значение. Кэширование произойдёт только если все указанные заголовки совпадают.

Регулярные выражения для заголовков

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

Пример:

new CacheableResponsePlugin({
  headers: {
    'Content-Type': /^application\/json/  // любые JSON-ответы
  }
})

В данном примере кэшируются только ответы с заголовком Content-Type, начинающимся с application/json.


Комбинирование фильтрации по статусу и заголовкам

Часто необходимо одновременно учитывать HTTP-статус и заголовки ответа. Плагин CacheableResponsePlugin поддерживает такую комбинацию:

new CacheableResponsePlugin({
  statuses: [200, 201],
  headers: {
    'X-Feature-Flag': 'enabled',
    'Cache-Control': 'public'
  }
})

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


Динамическая проверка заголовков через кастомный плагин

Если нужно более гибкое управление, Workbox позволяет создавать собственные плагины для проверки заголовков. Кастомный плагин может реализовывать метод cacheWillUpdate, который вызывается перед сохранением ответа в кэш.

Пример кастомного плагина:

const customHeaderPlugin = {
  cacheWillUpdate: async ({response}) => {
    if (!response) return null;

    const featureFlag = response.headers.get('X-Feature-Flag');
    if (featureFlag === 'enabled') {
      return response;  // разрешить кэширование
    }
    return null;  // отклонить кэширование
  }
};

registerRoute(
  ({request}) => request.destination === 'script',
  new StaleWhileRevalidate({
    cacheName: 'scripts-cache',
    plugins: [customHeaderPlugin]
  })
);

В этом примере сохраняются в кэш только скрипты с включённым флагом X-Feature-Flag.


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

  • Для статических ресурсов с известными заголовками лучше использовать CacheableResponsePlugin — это упрощает код и снижает вероятность ошибок.
  • Для динамических или вычисляемых заголовков предпочтительно применять кастомные плагины.
  • Всегда учитывать совместимость с кэшированием opaque-ответов (коды статуса 0) при работе с внешними API и CDN.
  • Регулярные выражения для заголовков позволяют избежать дублирования кода и сделать фильтрацию более гибкой.

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