Библиотека sw-precache предоставляет инструмент для генерации Service Worker, который автоматически кэширует ресурсы веб-приложения, обеспечивая оффлайн-доступ и ускорение загрузки страниц. Одним из ключевых аспектов является поведение при обновлении Service Worker, так как правильная организация этого процесса напрямую влияет на стабильность приложения и корректность кэшированных данных.
Когда Service Worker обновляется, браузер проходит несколько этапов: скачивание нового скрипта, установка, активация и управление клиентскими страницами. sw-precache предоставляет механизмы для тонкой настройки этого процесса.
Установка (install) – это этап, на котором новый
Service Worker получает возможность кэшировать указанные ресурсы. В
sw-precache это реализуется через массив precacheConfig,
содержащий пары URL и revision:
self.__precacheManifest = [
{ url: '/index.html', revision: '1234abcd' },
{ url: '/main.js', revision: '5678efgh' }
];
Если revision не изменился, Service Worker понимает, что
ресурс не требует обновления, что предотвращает лишнюю загрузку
данных.
Активация (activate) — этап, на котором старый
Service Worker заменяется новым. sw-precache автоматически удаляет
устаревшие кэшированные ресурсы, оставляя только актуальные. Этот
процесс основан на сравнении текущего и предыдущего
precacheConfig.
sw-precache предлагает несколько стратегий кэширования и обновления ресурсов, которые определяют, как приложение будет реагировать на изменения:
Cache-first Сначала возвращается кэшированный ресурс, только затем выполняется запрос к сети при отсутствии нужного файла. Применяется для статических ресурсов, таких как CSS, JS и шрифты.
Network-first Приоритет отдаётся сети, кэш используется только как резерв. Подходит для данных, которые часто обновляются, например, JSON с динамическим содержимым.
Stale-while-revalidate Сначала отдаётся кэшированный ресурс, одновременно загружая новую версию из сети и обновляя кэш. Позволяет обеспечить мгновенную загрузку страниц без устаревших данных.
При каждом обновлении Service Worker sw-precache создает новый кэш с
уникальным именем, включающим хеш ревизий файлов. Старые кэши
автоматически удаляются в фазе activate, что
гарантирует:
self.addEventListener('activate', event => {
const currentCaches = [CACHE_NAME];
event.waitUntil(
caches.keys().then(cacheNames => {
return Promise.all(
cacheNames.map(cacheName => {
if (!currentCaches.includes(cacheName)) {
return caches.delete(cacheName);
}
})
);
})
);
});
sw-precache по умолчанию использует поведение wait until all clients are closed. Это значит, что новый Service Worker будет ожидать, пока все вкладки с приложением, управляемым старым Service Worker, не закроются. После этого новый активируется и начинает обслуживать клиентов.
Для более агрессивного обновления можно использовать метод
skipWaiting():
self.addEventListener('install', event => {
self.skipWaiting();
});
Это заставляет новый Service Worker активироваться сразу после установки, минуя ожидание закрытия вкладок.
sw-precache генерирует статические списки для кэширования, но иногда необходимо обновлять динамические данные. Для этого используется комбинация sw-precache с runtime-кэшированием:
workbox.routing.registerRoute(
/\/api\/.*\/*.json/,
new workbox.strategies.NetworkFirst({
cacheName: 'api-cache',
networkTimeoutSeconds: 5,
plugins: [
new workbox.expiration.ExpirationPlugin({ maxEntries: 50, maxAgeSeconds: 86400 })
]
})
);
Это позволяет:
Для уведомления приложения о наличии новой версии Service Worker
sw-precache позволяет использовать событие controllerchange
на клиентской странице:
navigator.serviceWorker.addEventListener('controllerchange', () => {
console.log('Новая версия Service Worker активирована');
});
Таким образом, приложение может, например, предложить пользователю обновить страницу, чтобы применить изменения немедленно.
revision для всех статических
файлов, чтобы гарантировать обновление кэша при изменении контента.skipWaiting() с осторожностью: мгновенная
активация может прервать работу активных вкладок.Эффективная организация обновления Service Worker с sw-precache позволяет поддерживать актуальность ресурсов, минимизировать задержки и обеспечить стабильную работу веб-приложения.