sw-precache предоставляет возможность не только
автоматического кэширования ресурсов, но и гибкого контроля за
обновлениями сервис-воркера. Одним из ключевых механизмов
является использование postMessage для ручного
инициирования обновлений, что позволяет управлять жизненным
циклом сервис-воркера из клиентского кода.
Сервис-воркер может получать сообщения от страниц, которые он
обслуживает. Для этого используется метод postMessage:
// В клиентском коде
navigator.serviceWorker.controller.postMessage({
action: 'skipWaiting'
});
На стороне сервис-воркера необходимо обработать это сообщение:
self.addEventListener('message', event => {
if (event.data && event.data.action === 'skipWaiting') {
self.skipWaiting();
}
});
Ключевые моменты:
navigator.serviceWorker.controller существует только
если активен сервис-воркер для данной страницы.postMessage позволяет передавать объекты с
произвольными данными.skipWaiting() позволяет сервис-воркеру сразу
активироваться, минуя стандартное ожидание завершения всех открытых
вкладок.sw-precacheПри генерации service-worker.js через
sw-precache можно включить обработку
сообщений для контроля обновления:
importScripts('sw-toolbox.js');
self.addEventListener('message', function(event) {
if (event.data && event.data.action === 'skipWaiting') {
self.skipWaiting();
}
});
Сгенерированный service-worker.js автоматически кэширует
ресурсы, а добавленный блок для postMessage обеспечивает
мгновенное обновление без перезагрузки всех клиентов.
navigator.serviceWorker.register('/service-worker.js').then(registration => {
registration.onupdatefo und = () => {
const newWorker = registration.installing;
newWorker.onstatecha nge = () => {
if (newWorker.state === 'installed' && navigator.serviceWorker.controller) {
// Новый сервис-воркер установлен и готов к активации
console.log('Новая версия доступна');
}
};
};
});
function activateNewWorker() {
navigator.serviceWorker.getRegistration().then(reg => {
if (reg.waiting) {
reg.waiting.postMessage({ action: 'skipWaiting' });
}
});
}
Особенности:
reg.waiting содержит сервис-воркер, который завершил
установку, но ожидает активации.skipWaiting гарантирует, что новый воркер станет
активным, даже если вкладки с предыдущей версией открыты.После того как новый сервис-воркер активирован, старый воркер закрывается. Для корректной работы приложения важно уведомлять клиент:
navigator.serviceWorker.addEventListener('controllerchange', () => {
window.location.reload();
});
controllerchange срабатывает, когда новый
сервис-воркер начинает контролировать страницу.if (newWorker.state === 'installed') {
showUpdateBanner(() => {
newWorker.postMessage({ action: 'skipWaiting' });
});
}
postMessage.При работе с несколькими вкладками важно синхронизировать активацию
сервис-воркера. Один из подходов — использовать
BroadcastChannel для уведомления всех вкладок об
обновлении:
const channel = new BroadcastChannel('sw-updates');
channel.postMessage('update-available');
channel.onmess age = event => {
if (event.data === 'update-available') {
showUpdateBanner();
}
};
navigator.serviceWorker.controller перед вызовом
postMessage.skipWaiting автоматически без
уведомления пользователя, если обновление может нарушить текущую работу
приложения.sw-precache кэширует ресурсы.onupdatefound.postMessage с
skipWaiting.controllerchange инициирует обновление страницы
или другие действия.Такой подход обеспечивает точное управление обновлением без неожиданных перезапусков, дает возможность уведомлять пользователей и позволяет интегрировать сложные сценарии многовкладочного взаимодействия с сервис-воркером.