Обработка навигационных запросов

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

Навигационные запросы и их особенности

Навигационный запрос — это HTTP-запрос с методом GET, который браузер выполняет для загрузки HTML-страницы. Такие запросы имеют mode: "navigate", что позволяет отличить их от запросов за статическими ресурсами, API или ассетами. Обработка этих запросов требует особого внимания, поскольку неправильная стратегия может привести к некорректному рендерингу приложения при оффлайн-доступе или проблемам с кэшированием.

Регистрация маршрута для навигационных запросов

Workbox позволяет регистрировать маршруты через класс workbox.routing.Router или более удобные методы из workbox-routing. Для навигационных запросов обычно используется метод registerRoute с функцией-предикатом ({request}) => request.mode === 'navigate'.

Пример:

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

registerRoute(
  ({request}) => request.mode === 'navigate',
  new NetworkFirst({
    cacheName: 'pages-cache',
    networkTimeoutSeconds: 3,
    plugins: [
      // Можно добавить плагины для обработки кэширования или fallback
    ],
  })
);

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

Стратегии кэширования для навигационных запросов

Выбор стратегии зависит от требований приложения:

  • NetworkFirst — предпочтительно для динамических приложений, где важно отображать актуальный контент.
  • CacheFirst — подходит для статических страниц, редко обновляемых, когда приоритетом является скорость загрузки.
  • StaleWhileRevalidate — полезно, когда нужно показать кэшированную версию мгновенно, а сеть используется для обновления кэша на фоне.

Использование плагинов, таких как ExpirationPlugin или CacheableResponsePlugin, позволяет управлять временем жизни кэша и фильтровать ответы по статусу HTTP.

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

import {ExpirationPlugin} from 'workbox-expiration';
import {CacheableResponsePlugin} from 'workbox-cacheable-response';

new NetworkFirst({
  cacheName: 'pages-cache',
  plugins: [
    new ExpirationPlugin({
      maxEntries: 50,
      maxAgeSeconds: 24 * 60 * 60, // сутки
    }),
    new CacheableResponsePlugin({
      statuses: [0, 200],
    }),
  ],
});

Обработка ошибок и fallback

В PWA важно предусматривать fallback страницу, которая возвращается, если ни сеть, ни кэш не доступны. Это позволяет предотвратить показ пустой страницы при оффлайн-режиме.

registerRoute(
  ({request}) => request.mode === 'navigate',
  async ({event}) => {
    try {
      return await new NetworkFirst({
        cacheName: 'pages-cache',
      }).handle({event});
    } catch (error) {
      return caches.match('/offline.html');
    }
  }
);

Применение предикатов и регулярных выражений

Для сложных маршрутов можно использовать регулярные выражения, чтобы исключить определённые URL или обрабатывать только конкретные секции приложения:

registerRoute(
  ({request, url}) => request.mode === 'navigate' && !url.pathname.startsWith('/admin'),
  new NetworkFirst({cacheName: 'pages-cache'})
);

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

Особенности работы с SPA

Для одностраничных приложений (SPA) навигационные запросы чаще всего нужно перенаправлять на главный index.html, чтобы фронтенд-роутинг работал корректно. В Workbox это реализуется через предикат:

registerRoute(
  ({request}) => request.mode === 'navigate',
  async () => caches.match('/index.html')
);

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

Рекомендации по производительности

  • Ограничивать количество кэшируемых страниц через maxEntries.
  • Контролировать срок хранения с помощью maxAgeSeconds.
  • Использовать networkTimeoutSeconds в NetworkFirst для предотвращения долгих задержек при медленной сети.
  • В SPA избегать кэширования API-запросов через навигационный маршрут, чтобы данные всегда оставались актуальными.

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

При сборке проекта с помощью workbox-webpack-plugin или workbox-build можно автоматически генерировать сервис-воркер с маршрутом навигации:

new WorkboxPlugin.GenerateSW({
  clientsClaim: true,
  skipWaiting: true,
  navigateFallback: '/index.html',
  runtimeCaching: [
    {
      urlPattern: ({request}) => request.mode === 'navigate',
      handler: 'NetworkFirst',
      options: {
        cacheName: 'pages-cache',
        networkTimeoutSeconds: 3,
        expiration: {
          maxEntries: 50,
          maxAgeSeconds: 24 * 60 * 60,
        },
      },
    },
  ],
});

Этот подход минимизирует ручное написание маршрутов и обеспечивает единообразное кэширование страниц при оффлайн-доступе.

Особенности дебага

Для проверки работы навигационного кэширования полезно использовать:

  • Chrome DevTools → Application → Service Workers.
  • Включение режима “Offline” и проверка загрузки страниц.
  • Проверка кэша через caches.keys() и caches.match() в консоли.

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

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