Отлов запросов вне зарегистрированных маршрутов

Workbox предоставляет разработчику гибкие инструменты для управления кешированием и обработкой сетевых запросов в сервис-воркере. Помимо стандартной регистрации маршрутов через workbox.routing.registerRoute, существует возможность отлавливать запросы, которые не соответствуют никакому зарегистрированному маршруту. Это особенно полезно для реализации fallback-механизмов, логирования или обработки нестандартных запросов.


Использование catchHandler для глобальной обработки ошибок

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

Пример регистрации глобального обработчика:

import { setCatchHandler } from 'workbox-routing';

setCatchHandler(async ({event}) => {
  if (event.request.destination === 'document') {
    return caches.match('/offline.html');
  }
  return Response.error();
});

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

  • event.request.destination позволяет определить тип запроса (document, image, script, style и т.д.).
  • Возврат Response.error() сигнализирует о том, что запрос завершился с ошибкой.
  • Можно подставлять статические fallback-ресурсы для разных типов запросов.

Перехват запросов вне маршрутов через маршрут с matchCallback

В Workbox можно создать маршрут, который срабатывает для всех запросов, и использовать его как catch-all для “непойманных” запросов. Для этого применяется функция matchCallback, которая возвращает true только для запросов, не соответствующих другим маршрутам.

Пример реализации catch-all маршрута:

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

registerRoute(
  ({url, request}) => {
    // Логика фильтрации: возвращаем true, если запрос не был обработан ранее
    // Обычно это последний маршрут в списке
    return true;
  },
  new NetworkFirst({
    cacheName: 'fallback-cache',
    plugins: [
      {
        requestWillFetch: async ({request}) => {
          console.log('Запрос вне зарегистрированных маршрутов:', request.url);
          return request;
        }
      }
    ]
  })
);

Особенности такого подхода:

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

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

Workbox поддерживает плагины, которые можно применять глобально к стратегиями или отдельным маршрутам. Плагины позволяют:

  • Логировать запросы, не подходящие под маршруты.
  • Добавлять fallback-контент.
  • Модифицировать ответы перед отправкой клиенту.

Пример глобального плагина:

const fallbackPlugin = {
  async fetchDidFail({originalRequest}) {
    console.warn('Необработанный запрос:', originalRequest.url);
    if (originalRequest.destination === 'image') {
      return caches.match('/images/fallback.png');
    }
    return Response.error();
  }
};

// Применение к стратегии
import { StaleWhileRevalidate } from 'workbox-strategies';

const defaultStrategy = new StaleWhileRevalidate({
  cacheName: 'default-cache',
  plugins: [fallbackPlugin]
});

Важно:

  • Плагин fetchDidFail срабатывает при неудачной сетевой загрузке.
  • Можно настроить разные fallback-ответы для различных типов ресурсов.
  • Подходит для универсального управления запросами вне маршрутов.

Рекомендации по проектированию catch-all логики

  1. Последовательность маршрутов имеет значение. Workbox применяет маршруты в порядке регистрации. Catch-all маршрут должен быть последним.
  2. Использование разных стратегий для разных типов ресурсов. Документы, скрипты, изображения могут требовать разных fallback-стратегий.
  3. Минимизировать нагрузку на сеть. Слишком агрессивная catch-all логика может приводить к лишним запросам.
  4. Сочетание кеширования и fallback. Стратегии NetworkFirst и CacheFirst с плагинами обеспечивают гибкую обработку нестандартных запросов.
  5. Логирование и аналитика. Отлов не зарегистрированных маршрутов позволяет выявлять новые типы запросов, которые требуют добавления маршрутов.

Пример комплексного подхода

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

// Основные маршруты
registerRoute(
  ({url}) => url.pathname.startsWith('/api/'),
  new NetworkFirst({cacheName: 'api-cache'})
);

registerRoute(
  ({request}) => request.destination === 'image',
  new CacheFirst({cacheName: 'images-cache'})
);

// Глобальный catch-all маршрут
registerRoute(
  () => true,
  new NetworkFirst({
    cacheName: 'fallback-cache'
  })
);

// Глобальный обработчик ошибок
setCatchHandler(async ({event}) => {
  if (event.request.destination === 'document') {
    return caches.match('/offline.html');
  }
  return Response.error();
});

В этом примере запросы обрабатываются в три этапа:

  1. Специфические маршруты: API и изображения.
  2. Catch-all маршрут: обработка любых оставшихся запросов.
  3. Fallback при ошибках: возвращение оффлайн-страницы или ошибка.

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