Стратегии для потоковой отдачи HTML

Работа с потоковой отдачей HTML в современных веб-приложениях требует точного контроля над кешированием и стратегиями запроса ресурсов. Библиотека Workbox предоставляет высокоуровневые API для конфигурации стратегий кеширования, которые обеспечивают как высокую производительность, так и актуальность данных.


Cache First и Network First для HTML

Cache First и Network First — базовые стратегии, применяемые для HTML-документов, но с разным поведением и назначением.

  • Cache First: сначала пытается вернуть ресурс из кеша, если не найден — делает сетевой запрос. Подходит для статического HTML, где приоритет — быстродействие. Пример:
import { registerRoute } from 'workbox-routing';
import { CacheFirst } from 'workbox-strategies';
import { ExpirationPlugin } from 'workbox-expiration';

registerRoute(
  ({ request }) => request.mode === 'navigate',
  new CacheFirst({
    cacheName: 'html-cache',
    plugins: [
      new ExpirationPlugin({
        maxEntries: 50,
        maxAgeSeconds: 24 * 60 * 60, // 1 день
      }),
    ],
  })
);
  • Network First: сначала делает сетевой запрос, при неудаче возвращает кешированную версию. Оптимально для HTML, часто обновляемого или динамического. Пример:
import { NetworkFirst } from 'workbox-strategies';

registerRoute(
  ({ request }) => request.mode === 'navigate',
  new NetworkFirst({
    cacheName: 'html-dynamic-cache',
    networkTimeoutSeconds: 3,
    plugins: [
      new ExpirationPlugin({
        maxEntries: 50,
        maxAgeSeconds: 12 * 60 * 60, // 12 часов
      }),
    ],
  })
);

Ключевой момент: для HTML рекомендуется использовать Network First, так как страницы часто обновляются и устаревший контент может негативно сказаться на пользовательском опыте.


Стратегия Stale-While-Revalidate

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

import { StaleWhileRevalidate } from 'workbox-strategies';

registerRoute(
  ({ request }) => request.mode === 'navigate',
  new StaleWhileRevalidate({
    cacheName: 'html-sw-r-cache',
    plugins: [
      new ExpirationPlugin({
        maxEntries: 50,
        maxAgeSeconds: 6 * 60 * 60, // 6 часов
      }),
    ],
  })
);

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


Работа с потоковым рендерингом и HTML-подгрузкой

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

  1. Определяются точки рендеринга в URL-паттернах.
  2. Настраивается отдельный кеш для каждой части приложения.
  3. Используется Network First для главной оболочки, Stale-While-Revalidate для подгружаемых блоков.

Пример регистрации маршрутов для потокового HTML:

registerRoute(
  ({ url }) => url.pathname.startsWith('/partials/'),
  new StaleWhileRevalidate({
    cacheName: 'html-partials-cache',
    plugins: [
      new ExpirationPlugin({ maxEntries: 100, maxAgeSeconds: 2 * 60 * 60 }),
    ],
  })
);

registerRoute(
  ({ request }) => request.mode === 'navigate' && !request.url.includes('/partials/'),
  new NetworkFirst({
    cacheName: 'html-main-cache',
    networkTimeoutSeconds: 5,
  })
);

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


Обработка ошибок и fallback-страницы

При использовании стратегий для HTML важно предусмотреть fallback-страницу, которая будет возвращаться при отсутствии сети и кеша:

import { precacheAndRoute } from 'workbox-precaching';

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

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

Ключевой момент: fallback позволяет поддерживать доступность сайта даже при полном отсутствии сети.


Настройка сроков хранения и очистки кеша

Использование ExpirationPlugin позволяет контролировать:

  • maxEntries — максимальное количество HTML-документов в кеше.
  • maxAgeSeconds — время хранения в секундах.

Дополнительно можно использовать cacheWillUpdate для фильтрации HTTP-ответов и исключения ошибок из кеша:

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

new NetworkFirst({
  cacheName: 'html-main-cache',
  plugins: [
    new CacheableResponsePlugin({ statuses: [0, 200] }),
    new ExpirationPlugin({ maxEntries: 50, maxAgeSeconds: 24 * 60 * 60 }),
  ],
});

Вывод: сочетание стратегий Network First или Stale-While-Revalidate с плагинами ExpirationPlugin и CacheableResponsePlugin обеспечивает корректную потоковую отдачу HTML с гарантией актуальности и надежности.