Плагин для сжатия и трансформации ответов

Workbox предоставляет мощный инструментарий для управления кэшированием и обработкой сетевых запросов в сервис-воркерах. Один из важных компонентов — возможность модифицировать ответы перед их сохранением в кэш или отправкой клиенту с помощью плагинов. Плагин для сжатия и трансформации ответов (Response Plugins) позволяет изменять содержимое ответа, применяя сжатие, фильтрацию или другие трансформации данных.

Основы работы с плагинами Workbox

Плагины Workbox представляют собой объекты с заранее определёнными методами, которые вызываются на определённых этапах жизненного цикла запроса:

  • cacheWillUpdate({response}) — вызывается перед сохранением ответа в кэш, позволяет определить, сохранять его или нет.
  • cacheDidUpdate({cacheName, request, oldResponse, newResponse}) — уведомление о том, что кэш был обновлён.
  • fetchDidSucceed({request, response}) — вызывается после успешного сетевого запроса.
  • fetchDidFail({request}) — вызывается при ошибке сетевого запроса.

Для плагина трансформации ответов ключевым методом является cacheWillUpdate, так как он позволяет перехватывать ответ и изменять его содержимое.

Создание плагина сжатия ответов

Сжатие данных перед кэшированием улучшает производительность и уменьшает объём используемого хранилища. Пример плагина для gzip-сжатия:

import {Plugin} from 'workbox-core';

const compressResponsePlugin = {
  async cacheWillUpdate({response}) {
    if (!response || response.status !== 200 || response.type !== 'basic') {
      return null;
    }

    const clonedResponse = response.clone();
    const data = await clonedResponse.arrayBuffer();

    // Пример сжатия с использованием pako
    import('pako').then(pako => {
      const compressed = pako.gzip(new Uint8Array(data));
      return new Response(compressed, {
        headers: {
          'Content-Type': 'application/octet-stream',
          'Content-Encoding': 'gzip',
        },
      });
    });
  }
};

Ключевые моменты:

  • Ответ нужно клонировать перед чтением, так как объект Response является потоковым.
  • В заголовках указывается Content-Encoding, чтобы клиент понимал, что данные сжаты.
  • Плагин возвращает новый объект Response, который попадёт в кэш.

Трансформация JSON-ответов

Иногда требуется изменить данные перед кэшированием, например, фильтровать поля или нормализовать объекты:

const transformJsonPlugin = {
  async cacheWillUpdate({response}) {
    if (!response || response.status !== 200) return null;
    const clonedResponse = response.clone();
    const jsonData = await clonedResponse.json();

    // Трансформация: оставляем только нужные поля
    const transformedData = jsonData.map(item => ({
      id: item.id,
      title: item.title
    }));

    return new Response(JSON.stringify(transformedData), {
      headers: {'Content-Type': 'application/json'}
    });
  }
};

Особенности:

  • Используется метод json() для работы с телом ответа.
  • После трансформации создаётся новый объект Response с обновлённым содержимым и корректными заголовками.
  • Можно совмещать с кэшированием стратегий Workbox (StaleWhileRevalidate, CacheFirst, NetworkFirst).

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

Плагины интегрируются в стратегии кэширования Workbox через массив plugins:

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

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

Принципы работы:

  • Стратегия вызывает плагины последовательно.
  • Результат метода cacheWillUpdate определяет, что попадёт в кэш.
  • Плагины могут быть цепочкой: один трансформирует данные, другой сжимает их.

Обработка ошибок и исключений

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

  • Использовать try-catch внутри методов плагина.
  • Возвращать null, если ответ не подходит для трансформации.
  • Логировать ошибки для отладки.

Пример безопасной трансформации:

const safeTransformPlugin = {
  async cacheWillUpdate({response}) {
    try {
      const cloned = response.clone();
      const data = await cloned.json();
      // Простая фильтрация
      const filtered = data.filter(item => item.active);
      return new Response(JSON.stringify(filtered), {
        headers: {'Content-Type': 'application/json'}
      });
    } catch (e) {
      console.error('Ошибка трансформации:', e);
      return null;
    }
  }
};

Заключение по применению

Плагин для сжатия и трансформации ответов позволяет:

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

Использование таких плагинов повышает гибкость и эффективность стратегий Workbox, позволяя создавать быстрые и компактные Progressive Web Apps.