В некоторых сценариях сервис-воркеру может потребоваться инициировать взаимодействие с любой из активных вкладок, которыми он управляет, чтобы сообщить о каком-либо событии. Примеры включают:
- Уведомление страницы о том, что установлена новая версия сервис-воркера, чтобы страница могла отобразить кнопку «Обновить для обновления», позволяющую пользователю немедленно получить доступ к новой функциональности.
- Информирование пользователя об изменении кэшированных данных, произошедшем на стороне сервис-воркера, путем отображения таких сообщений, как: «Приложение готово к работе в автономном режиме» или «Доступна новая версия контента» .

Мы будем называть подобные сценарии использования, когда сервис-воркеру не нужно получать сообщение от страницы для начала обмена данными , «широковещательными обновлениями» . В этом руководстве мы рассмотрим различные способы реализации такого рода обмена данными между страницами и сервис-воркерами, используя стандартные API браузера и библиотеку Workbox .
Производственные примеры
Tinder
Tinder PWA использует workbox-window для отслеживания важных моментов жизненного цикла сервис-воркера на странице («установлен», «управляется» и «активирован»). Таким образом, когда вступает в действие новый сервис-воркер, отображается баннер «Доступно обновление» , чтобы пользователи могли обновить PWA и получить доступ к новейшим функциям.

Скууш
В PWA-приложении Squoosh , когда сервис-воркер кэширует все необходимые ресурсы для работы в автономном режиме, он отправляет на страницу сообщение с всплывающим уведомлением «Готово к работе в автономном режиме», информируя пользователя о наличии этой функции:

Использование Workbox
Послушайте о событиях жизненного цикла работника сферы услуг.
workbox-window предоставляет простой интерфейс для отслеживания важных событий жизненного цикла сервис-воркера . Внутри библиотека использует клиентские API, такие как updatefound и statechange , и предоставляет высокоуровневые обработчики событий в объекте workbox-window , что упрощает пользователю обработку этих событий.
Приведенный ниже код страницы позволяет отслеживать каждую установку новой версии сервис-воркера, чтобы вы могли сообщить об этом пользователю:
const wb = new Workbox('/sw.js');
wb.addEventListener('installed', (event) => {
if (event.isUpdate) {
// Show "Update App" banner
}
});
wb.register();
Уведомить страницу об изменениях в кэшированных данных.
Пакет Workbox workbox-broadcast-update предоставляет стандартный способ уведомления клиентов Windows об обновлении кэшированного ответа. Чаще всего он используется в сочетании со стратегией StaleWhileRevalidate .
Для рассылки обновлений добавьте broadcastUpdate.BroadcastUpdatePlugin в параметры стратегии на стороне сервис-воркера:
import {registerRoute} from 'workbox-routing';
import {StaleWhileRevalidate} from 'workbox-strategies';
import {BroadcastUpdatePlugin} from 'workbox-broadcast-update';
registerRoute(
({url}) => url.pathname.startsWith('/api/'),
new StaleWhileRevalidate({
plugins: [
new BroadcastUpdatePlugin(),
],
})
);
В вашем веб-приложении вы можете отслеживать эти события следующим образом:
navigator.serviceWorker.addEventListener('message', async (event) => {
// Optional: ensure the message came from workbox-broadcast-update
if (event.data.meta === 'workbox-broadcast-update') {
const {cacheName, updatedUrl} = event.data.payload;
// Do something with cacheName and updatedUrl.
// For example, get the cached content and update
// the content on the page.
const cache = await caches.open(cacheName);
const updatedResponse = await cache.match(updatedUrl);
const updatedText = await updatedResponse.text();
}
});
Использование API браузера
Если функционала Workbox недостаточно для ваших нужд, используйте следующие API браузера для реализации «широковещательных обновлений» :
API для трансляций
Сервис-воркер создает объект BroadcastChannel и начинает отправлять в него сообщения. Любой контекст (например, страница), заинтересованный в получении этих сообщений, может создать экземпляр объекта BroadcastChannel и реализовать обработчик сообщений для их приема.
Чтобы сообщить странице о установке нового сервис-воркера, используйте следующий код:
// Create Broadcast Channel to send messages to the page
const broadcast = new BroadcastChannel('sw-update-channel');
self.addEventListener('install', function (event) {
// Inform the page every time a new service worker is installed
broadcast.postMessage({type: 'CRITICAL_SW_UPDATE'});
});
Страница отслеживает эти события, подписавшись на sw-update-channel :
// Create Broadcast Channel and listen to messages sent to it
const broadcast = new BroadcastChannel('sw-update-channel');
broadcast.onmessage = (event) => {
if (event.data && event.data.type === 'CRITICAL_SW_UPDATE') {
// Show "update to refresh" banner to the user.
}
};
Это простой метод, но его ограничение связано с поддержкой браузеров: на момент написания этой статьи Safari не поддерживает этот API .
Клиентский API
API клиента предоставляет простой способ взаимодействия с несколькими клиентами из сервис-воркера путем итерации по массиву объектов Client .
Используйте следующий код сервис-воркера для отправки сообщения на последнюю активную вкладку:
// Obtain an array of Window client objects
self.clients.matchAll(options).then(function (clients) {
if (clients && clients.length) {
// Respond to last focused tab
clients[0].postMessage({type: 'MSG_ID'});
}
});
На странице реализован обработчик сообщений для перехвата этих сообщений:
// Listen to messages
navigator.serviceWorker.onmessage = (event) => {
if (event.data && event.data.type === 'MSG_ID') {
// Process response
}
};
Клиентский API — отличный вариант для таких случаев, как передача информации на несколько активных вкладок. API поддерживается всеми основными браузерами, но не все его методы. Перед использованием проверьте поддержку браузера.
Канал сообщений
Для работы с каналом сообщений требуется начальный этап настройки, заключающийся в передаче порта со страницы в сервис-воркер для установления канала связи между ними. Страница создает объект MessageChannel и передает порт сервис-воркеру через интерфейс postMessage() :
const messageChannel = new MessageChannel();
// Init port
navigator.serviceWorker.controller.postMessage({type: 'PORT_INITIALIZATION'}, [
messageChannel.port2,
]);
Страница прослушивает сообщения, реализуя обработчик «onmessage» на этом порту:
// Listen to messages
messageChannel.port1.onmessage = (event) => {
// Process message
};
Сервис-воркер получает порт и сохраняет ссылку на него:
// Initialize
let communicationPort;
self.addEventListener('message', (event) => {
if (event.data && event.data.type === 'PORT_INITIALIZATION') {
communicationPort = event.ports[0];
}
});
С этого момента можно отправлять сообщения на страницу, вызывая postMessage() в ссылке на порт:
// Communicate
communicationPort.postMessage({type: 'MSG_ID' });
Реализация MessageChannel может быть более сложной из-за необходимости инициализации портов, но он поддерживается всеми основными браузерами .
Следующие шаги
В этом руководстве мы рассмотрели один конкретный случай взаимодействия Windows с сервис-воркером: «широковещательные обновления» . Рассмотренные примеры включают в себя прослушивание важных событий жизненного цикла сервис-воркера и передачу странице информации об изменениях контента или кэшированных данных. Можно придумать и более интересные варианты использования, когда сервис-воркер инициирует взаимодействие со страницей, не получая никаких сообщений заранее.
Для получения дополнительной информации о моделях взаимодействия между окнами Windows и сервисными работниками, ознакомьтесь с:
- Руководство по императивному кэшированию : вызов сервис-воркера со страницы для предварительного кэширования ресурсов (например, в сценариях предварительной загрузки).
- Двусторонняя связь : делегирование задачи сотруднику сервисной службы (например, загрузка большого объема данных) и информирование страницы о ходе выполнения.