Service Worker в контексте Workbox является отдельным скриптом,
который выполняется в отдельном потоке браузера, независимо от основной
страницы. Это значит, что прямой доступ к DOM недоступен, и обмен
данными осуществляется через механизм сообщений. В JavaScript для
передачи информации между основной страницей и воркером используются
события postMessage и слушатели message.
В Workbox для удобства работы с сообщениями можно использовать
встроенный объект workbox.core.clientsClaim() и методы
регистрации Service Worker, которые упрощают коммуникацию.
Для передачи данных из страницы в воркер применяется метод
postMessage. Пример базовой схемы:
if ('serviceWorker' in navigator) {
navigator.serviceWorker.ready.then(registration => {
registration.active.postMessage({
type: 'CACHE_URL',
payload: '/path/to/resource'
});
});
}
Ключевые моменты:
registration.active — текущий активный Service
Worker.type и
payload для структурирования данных.navigator.serviceWorker.ready гарантирует, что
воркер полностью активен и готов к приему сообщений.В Service Worker устанавливается слушатель события
message для обработки входящих сообщений:
self.addEventListener('message', (event) => {
const { type, payload } = event.data;
switch(type) {
case 'CACHE_URL':
caches.open('dynamic-cache').then(cache => cache.add(payload));
break;
default:
console.log('Неизвестный тип сообщения:', type);
}
});
Особенности обработки:
event.data содержит переданные с страницы данные.switch или if для разных
типов сообщений позволяет строить масштабируемую систему команд.Service Worker может отправлять данные обратно с использованием
объекта clients:
self.clients.matchAll().then(clients => {
clients.forEach(client => {
client.postMessage({
type: 'CACHE_COMPLETE',
payload: { url: '/path/to/resource' }
});
});
});
Важные моменты:
self.clients.matchAll() возвращает список всех
контролируемых клиентов (вкладок, окон) текущего Service Worker.postMessage, что позволяет
уведомлять сразу несколько страниц.type для различения событий.Страница подписывается на сообщения от Service Worker через объект
navigator.serviceWorker:
navigator.serviceWorker.addEventListener('message', event => {
const { type, payload } = event.data;
switch(type) {
case 'CACHE_COMPLETE':
console.log('Ресурс закеширован:', payload.url);
break;
default:
console.log('Неизвестный тип сообщения от воркера:', type);
}
});
Особенности:
switch облегчает масштабирование, когда
воркер обрабатывает множество событий.Workbox предоставляет вспомогательные методы для работы с событиями
message и кэшированием. Например,
workbox.routing можно совместить с передачей команд:
import { registerRoute } from 'workbox-routing';
import { CacheFirst } from 'workbox-strategies';
registerRoute(
({ request }) => request.destination === 'image',
new CacheFirst({
cacheName: 'images-cache'
})
);
self.addEventListener('message', (event) => {
if(event.data && event.data.type === 'SKIP_WAITING') {
self.skipWaiting();
}
});
Пояснения:
SKIP_WAITING мгновенно активирует новый воркер,
что полезно при обновлении приложения.Для передачи объектов с массивами, буферами или бинарными данными
используется StructuredClone алгоритм, встроенный в
postMessage. Он позволяет передавать практически любые
JavaScript-объекты:
navigator.serviceWorker.controller.postMessage({
type: 'UPLOAD_DATA',
payload: { buffer: new Uint8Array([1,2,3,4]) }
});
На стороне воркера эти данные принимаются без дополнительного преобразования, что упрощает работу с медиафайлами и большими массивами данных.
Эта архитектура позволяет строить надежное и масштабируемое взаимодействие между основной страницей и Service Worker с использованием Workbox, минимизируя риски потери данных и обеспечивая гибкое управление кэшированием и событиями.