Fallback-страницы и fallback-ответы

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


Понятие fallback

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

  • HTML-страница — отображается при недоступности страницы (например, offline.html).
  • JSON или другой API-ответ — возвращается при ошибках сети для API-запросов.
  • Изображения или медиа — подставляется заглушка вместо недоступного контента.

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


Использование workbox.routing.setCatchHandler

Для настройки fallback Workbox использует метод setCatchHandler, который позволяет определить глобальную функцию обработки ошибок при запросах.

Пример настройки fallback-страницы для HTML:

import {registerRoute} from 'workbox-routing';
import {NetworkOnly} from 'workbox-strategies';
import {setCatchHandler} from 'workbox-routing';
import {precacheAndRoute} from 'workbox-precaching';

precacheAndRoute([
  {url: '/offline.html', revision: '1'},
]);

registerRoute(
  ({request}) => request.destination === 'document',
  new NetworkOnly()
);

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

Объяснение работы кода:

  1. precacheAndRoute обеспечивает предварительное кэширование страницы /offline.html.
  2. registerRoute с стратегией NetworkOnly означает, что HTML-страницы всегда запрашиваются из сети.
  3. setCatchHandler перехватывает ошибки сети и подставляет кэшированную offline-страницу при недоступности документа.

Fallback для API и JSON

Для API-запросов полезно возвращать заранее подготовленные JSON-ответы или пустые объекты вместо ошибки.

Пример:

setCatchHandler(async ({event}) => {
  if (event.request.destination === 'document') {
    return caches.match('/offline.html');
  } else if (event.request.url.includes('/api/')) {
    return new Response(JSON.stringify({error: 'Нет соединения'}), {
      headers: {'Content-Type': 'application/json'},
    });
  }
  return Response.error();
});

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


Fallback для изображений

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

setCatchHandler(async ({event}) => {
  if (event.request.destination === 'image') {
    return caches.match('/images/fallback.png');
  }
  return Response.error();
});

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


Комбинирование с различными стратегиями кэширования

Fallback удобно комбинировать с различными стратегиями Workbox:

  • NetworkFirst: сначала пробуем сеть, затем кэш, если сеть недоступна. Fallback срабатывает при недоступности и кэша.
  • CacheFirst: сначала пробуем кэш, fallback используется только если ресурс отсутствует в кэше и сети.
  • StaleWhileRevalidate: всегда возвращает кэшированную версию и обновляет её в фоне, fallback позволяет показывать запасной вариант в случае ошибок.

Пример использования с NetworkFirst:

import {NetworkFirst} from 'workbox-strategies';

registerRoute(
  ({request}) => request.destination === 'document',
  new NetworkFirst({
    cacheName: 'pages-cache',
    plugins: [
      {
        fetchDidFail: async () => caches.match('/offline.html')
      }
    ]
  })
);

Рекомендации по проектированию fallback

  1. Минимизировать вес fallback — offline-страницы и заглушки должны быть лёгкими, чтобы быстро загружаться.
  2. Кэшировать заранее — fallback должен быть предварительно закэширован, чтобы гарантировать доступность офлайн.
  3. Дифференцировать по типу ресурсов — HTML, API, изображения требуют разных fallback.
  4. Явно обрабатывать ошибки сети — использование setCatchHandler позволяет централизованно управлять всеми ошибками.

Поддержка мультиязычности

Для мультиязычных сайтов рекомендуется кэшировать несколько версий fallback и подставлять нужную в зависимости от локали:

precacheAndRoute([
  {url: '/offline-en.html', revision: '1'},
  {url: '/offline-ru.html', revision: '1'},
]);

setCatchHandler(async ({event}) => {
  const lang = navigator.language.startsWith('ru') ? 'ru' : 'en';
  if (event.request.destination === 'document') {
    return caches.match(`/offline-${lang}.html`);
  }
  return Response.error();
});

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