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

Workbox предоставляет мощный набор инструментов для управления кэшированием и маршрутизацией ресурсов в Progressive Web Apps. Одной из ключевых задач является корректная обработка навигационных запросов, особенно когда приложение использует single-page architecture (SPA). В таких приложениях большинство URL должны обслуживаться одним HTML-файлом, обычно index.html, что требует особого подхода при precaching.


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

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

  • Навигационный запрос отличается от запросов за изображениями, скриптами или стилями.
  • Его необходимо обрабатывать отдельно, чтобы приложение корректно загружалось оффлайн.
  • Workbox предоставляет NavigationRoute и стратегии маршрутизации для работы с precached HTML.

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

import { precacheAndRoute } from 'workbox-precaching';
import { registerRoute, NavigationRoute } from 'workbox-routing';
import { NetworkFirst } from 'workbox-strategies';

// Предварительное кэширование ресурсов
precacheAndRoute(self.__WB_MANIFEST);

// Настройка стратегии для навигационных запросов
const networkFirstHandler = new NetworkFirst({
  cacheName: 'html-cache',
});

const navigationRoute = new NavigationRoute(networkFirstHandler);
registerRoute(navigationRoute);

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

  • NetworkFirst гарантирует, что будет загружена свежая версия HTML, если есть соединение, иначе берется кэш.
  • NavigationRoute автоматически фильтрует запросы и обрабатывает только навигационные.

Фильтрация запросов

Workbox позволяет задавать кастомные правила фильтрации для навигационных маршрутов через allowlist и denylist. Это важно, чтобы не обрабатывать через HTML запросы к API, статическим ресурсам или service worker файлам.

Пример:

const navigationRoute = new NavigationRoute(networkFirstHandler, {
  denylist: [
    new RegExp('/api/'),       // Не обрабатывать API-запросы
    new RegExp('/admin/'),     // Исключить административные страницы
    /\.js$/,                   // Исключить JS-файлы
  ],
});

registerRoute(navigationRoute);

Интеграция с precaching

Когда используется precacheAndRoute, все ресурсы, указанные в манифесте, автоматически кэшируются при установке Service Worker. Для SPA важно, чтобы index.html тоже был включён в precache. Тогда NavigationRoute может отдавать его из кэша при отсутствии сети, обеспечивая оффлайн-доступ.

Пример структуры манифеста:

self.__WB_MANIFEST = [
  { url: '/index.html', revision: '123456' },
  { url: '/styles/main.css', revision: '123456' },
  { url: '/scripts/app.js', revision: '123456' },
];

В этом случае, навигационные запросы всегда будут возвращать актуальный HTML, а остальные ресурсы загружаться через precache или runtime caching.


Особенности стратегий для навигации

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

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

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

Для SPA критично обрабатывать сценарий, когда сеть недоступна и HTML не найден в кэше. В Workbox можно задать fallback ресурс:

const networkFirstHandler = new NetworkFirst({
  cacheName: 'html-cache',
  plugins: [{
    fetchDidFail: async ({ request }) => {
      return caches.match('/offline.html');
    }
  }],
});

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

Это обеспечивает корректное поведение приложения даже при полной потере соединения.


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

  • Всегда включать только необходимые ресурсы в precache.
  • Ограничивать denylist навигационных маршрутов, чтобы исключить запросы к API или статическим файлам.
  • Для крупных SPA использовать NetworkFirst с кэшированием HTML, чтобы минимизировать задержку при оффлайн-доступе.
  • Регулярно обновлять ревизии файлов для корректного обновления кэша пользователям.

Итоговые практики

  • Навигационные запросы SPA обрабатываются отдельно от статических ресурсов.
  • NavigationRoute в связке с NetworkFirst обеспечивает баланс между оффлайн-доступом и актуальностью HTML.
  • precache должен включать главный HTML и важные статические файлы.
  • Настройка denylist предотвращает конфликт маршрутов и ошибок при обращении к API или другим ресурсам.

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