Workbox — это библиотека от Google, предназначенная для упрощения работы с сервис-воркерами и реализации стратегий кэширования в веб-приложениях. В многостраничных приложениях (MPA) её использование требует специфического подхода, так как каждая страница может иметь собственные скрипты, стили и ресурсы. Основная цель — улучшение производительности и оффлайн-доступности без значительного изменения существующей архитектуры.
Сервис-воркер регистрируется в основном JavaScript-файле каждой страницы или в общем скрипте, который подключается ко всем страницам:
if ('serviceWorker' in navigator) {
window.addEventListener('load', () => {
navigator.serviceWorker.register('/sw.js').then(registration => {
console.log('Service Worker зарегистрирован с областью:', registration.scope);
}).catch(error => {
console.log('Регистрация Service Worker не удалась:', error);
});
});
}
Ключевое значение здесь имеет область регистрации
(scope), которая определяет, какие URL будут обслуживаться
сервис-воркером. В MPA часто используется корневая область
('/') для покрытия всех страниц.
Workbox предоставляет модуль workbox-core для базовой
настройки и workbox-precaching,
workbox-routing, workbox-strategies для
кэширования ресурсов и маршрутизации запросов.
Пример sw.js:
import {registerRoute} from 'workbox-routing';
import {StaleWhileRevalidate} from 'workbox-strategies';
import {precacheAndRoute} from 'workbox-precaching';
// Пресейвинг статических файлов
precacheAndRoute(self.__WB_MANIFEST);
// Маршрутизация всех CSS и JS с стратегией StaleWhileRevalidate
registerRoute(
({request}) => request.destination === 'style' || request.destination === 'script',
new StaleWhileRevalidate({
cacheName: 'static-resources',
})
);
// Кэширование изображений с лимитом на 60 элементов
registerRoute(
({request}) => request.destination === 'image',
new StaleWhileRevalidate({
cacheName: 'images',
plugins: [
new workbox.expiration.ExpirationPlugin({
maxEntries: 60,
maxAgeSeconds: 30 * 24 * 60 * 60, // 30 дней
}),
],
})
);
В многостраничных приложениях важно предусмотреть кэширование HTML страниц. Workbox позволяет явно перечислить страницы для пресейвинга:
precacheAndRoute([
{url: '/index.html', revision: '123456'},
{url: '/about.html', revision: '123457'},
{url: '/contact.html', revision: '123458'},
]);
Ключевой момент: каждая HTML-страница должна иметь
уникальный revision или хэш, чтобы при обновлении контента
старый кэш автоматически заменялся.
Workbox поддерживает несколько стратегий кэширования, которые выбираются в зависимости от типа ресурса:
Пример Network First для страниц:
registerRoute(
({request}) => request.destination === 'document',
new workbox.strategies.NetworkFirst({
cacheName: 'html-pages',
plugins: [
new workbox.expiration.ExpirationPlugin({
maxEntries: 50,
maxAgeSeconds: 7 * 24 * 60 * 60, // 7 дней
}),
],
})
);
MPA часто обновляются фрагментарно. Чтобы сервис-воркер корректно обновлял кэш:
revision или
хэш.__WB_MANIFEST) с актуальными ревизиями.workbox-core.skipWaiting() для
немедленной активации нового сервис-воркера.import {skipWaiting, clientsClaim} from 'workbox-core';
skipWaiting();
clientsClaim();
Эти вызовы позволяют новому сервис-воркеру сразу управлять всеми страницами и обновлять устаревшие кэши.
Для API-запросов используют стратегию Network First с ограничением по количеству элементов и сроку жизни:
registerRoute(
({url}) => url.pathname.startsWith('/api/'),
new workbox.strategies.NetworkFirst({
cacheName: 'api-cache',
networkTimeoutSeconds: 5,
plugins: [
new workbox.expiration.ExpirationPlugin({
maxEntries: 30,
maxAgeSeconds: 60 * 60, // 1 час
}),
],
})
);
Особенность MPA: API-запросы могут использоваться на нескольких страницах, поэтому важно унифицировать их кэш.
Workbox позволяет кэшировать страницы и ресурсы по мере их посещения:
registerRoute(
({request}) => request.destination === 'document',
new workbox.strategies.StaleWhileRevalidate({
cacheName: 'dynamic-pages',
})
);
Эта стратегия подходит для страниц, которые не входят в пресейвинг, но часто посещаются пользователями.
Для контроля работы сервис-воркера и стратегий Workbox можно включить логирование:
import {setConfig} from 'workbox-core';
setConfig({debug: true});
Это позволит отслеживать, какие ресурсы кэшируются, обновляются или извлекаются из сети.