Workbox предоставляет мощные инструменты для управления кэшированием и стратегиями загрузки ресурсов, однако при работе с несколькими вкладками одного приложения возникает задача синхронизации версий сервис-воркера. Без корректной синхронизации новые версии приложения могут быть доступны в одной вкладке, но другие вкладки будут использовать старые ресурсы. Это может приводить к рассинхронизации состояния интерфейса и неконсистентности данных.
Для отслеживания обновлений Workbox использует события жизненного
цикла сервис-воркера: install, activate,
waiting, controlling. Ключевое событие для
синхронизации версий между вкладками — waiting. Когда новая
версия сервис-воркера установлена, но ещё не активирована, она попадает
в состояние waiting. Это сигнализирует о том, что есть
новая версия приложения, и все открытые вкладки должны быть
оповещены.
self.addEventListener('install', (event) => {
console.log('Service Worker: установлен');
});
self.addEventListener('activate', (event) => {
console.log('Service Worker: активирован');
});
self.addEventListener('waiting', () => {
console.log('Service Worker: новая версия готова к активации');
});
Для синхронизации вкладок эффективно применять API
BroadcastChannel. Он позволяет открытым вкладкам
обмениваться сообщениями в реальном времени. При обнаружении новой
версии сервис-воркера одна вкладка может отправить уведомление другим
вкладкам.
const channel = new BroadcastChannel('sw-messages');
channel.addEventListener('message', (event) => {
if (event.data.type === 'NEW_VERSION_AVAILABLE') {
console.log('Обнаружена новая версия приложения');
// Логика обновления интерфейса или перезагрузки вкладки
}
});
Сервис-воркер может отправлять сообщения всем вкладкам через
clients.matchAll:
self.addEventListener('install', (event) => {
self.skipWaiting(); // пропускаем фазу ожидания при необходимости
});
self.addEventListener('activate', async () => {
const clientsList = await self.clients.matchAll({ type: 'window' });
clientsList.forEach(client => {
client.postMessage({ type: 'NEW_VERSION_AVAILABLE' });
});
});
Для минимизации рассинхронизации можно реализовать автоматическое
обновление вкладки при обнаружении новой версии. После получения события
NEW_VERSION_AVAILABLE вкладка может показать уведомление
пользователю или перезагрузить страницу автоматически:
channel.addEventListener('message', (event) => {
if (event.data.type === 'NEW_VERSION_AVAILABLE') {
window.location.reload();
}
});
Workbox поддерживает версионированные кэши через
cacheNameDetails. Это позволяет создать отдельный кэш для
каждой версии приложения. При активации новой версии сервис-воркера
старый кэш можно удалить:
workbox.core.setCacheNameDetails({
prefix: 'my-app',
suffix: 'v1', // изменяется при выпуске новой версии
precache: 'precache',
runtime: 'runtime'
});
self.addEventListener('activate', async () => {
const cacheNames = await caches.keys();
await Promise.all(
cacheNames
.filter(name => !name.includes('v1'))
.map(name => caches.delete(name))
);
});
skipWaiting) – обеспечивает немедленное
обновление, но может прервать активные сессии.window.location.reload() без
уведомления пользователя в критически важных приложениях, где потеря
состояния недопустима.hash
сборки) для контроля состояния кэшей.Синхронизация версий между вкладками позволяет поддерживать
консистентное состояние приложения и предотвращает ошибки из-за
использования старых ресурсов. Комбинация возможностей Workbox, событий
жизненного цикла сервис-воркера и BroadcastChannel
обеспечивает надежный и масштабируемый механизм обновления.