Работа с потоковой отдачей HTML в современных веб-приложениях требует точного контроля над кешированием и стратегиями запроса ресурсов. Библиотека Workbox предоставляет высокоуровневые API для конфигурации стратегий кеширования, которые обеспечивают как высокую производительность, так и актуальность данных.
Cache First и Network 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 день
}),
],
})
);
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, так как страницы часто обновляются и
устаревший контент может негативно сказаться на пользовательском
опыте.
Эта стратегия сочетает быстрое отображение кеша с асинхронным обновлением ресурса. При первом запросе возвращается кешированная версия, а в фоне выполняется сетевой запрос для обновления кеша.
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-кеш автоматически обновляется для будущих запросов.
Для приложений с динамической подгрузкой контента (например, SPA) важна поддержка streaming HTML. Workbox позволяет интегрироваться с серверным рендерингом, обеспечивая кеширование отдельных фрагментов HTML. Для этого:
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,
})
);
Особенность: кеширование по частям снижает нагрузку на сеть и ускоряет отрисовку страниц, особенно при слабом соединении.
При использовании стратегий для 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 с гарантией актуальности и надежности.