Clients API предоставляет интерфейс для взаимодействия с открытыми вкладками (clients) веб-приложения через сервис-воркер. С помощью этого API можно получать список активных клиентов, отправлять им сообщения, а также контролировать поведение навигации и обновления страниц. В контексте Workbox взаимодействие с Clients API чаще всего используется для реализации стратегий кеширования, push-уведомлений и управления обновлениями приложения.
Метод clients.matchAll() позволяет получить массив
объектов Client, представляющих открытые вкладки или окна приложения.
Пример использования в сервис-воркере:
self.addEventListener('activate', async (event) => {
const allClients = await clients.matchAll({ includeUncontrolled: true });
allClients.forEach(client => {
console.log('Client URL:', client.url);
});
});
Ключевые параметры matchAll:
includeUncontrolled — включает вкладки, которые ещё не
контролируются текущим сервис-воркером.type — фильтр по типу клиента ('window',
'worker' или 'sharedworker').Workbox не предоставляет отдельного метода для работы с Clients API, поэтому используются стандартные методы сервис-воркеров:
async function sendMessageToClients(message) {
const allClients = await clients.matchAll({ type: 'window' });
for (const client of allClients) {
client.postMessage(message);
}
}
self.addEventListener('push', event => {
const payload = event.data.json();
event.waitUntil(sendMessageToClients({ type: 'PUSH_RECEIVED', payload }));
});
client.postMessage позволяет передавать объекты данных в
открытые вкладки. На стороне клиента их можно обработать с помощью
события navigator.serviceWorker.onmessage.
Для двусторонней коммуникации удобно использовать
MessageChannel:
self.addEventListener('fetch', event => {
event.respondWith((async () => {
const allClients = await clients.matchAll({ type: 'window' });
if (allClients.length > 0) {
const client = allClients[0];
const messageChannel = new MessageChannel();
messageChannel.port1.onmess age = (event) => {
console.log('Ответ от клиента:', event.data);
};
client.postMessage({ type: 'PING' }, [messageChannel.port2]);
}
return fetch(event.request);
})());
});
Использование MessageChannel позволяет получать
асинхронный ответ от клиента, что особенно полезно для
динамического управления состоянием приложения.
Методы client.navigate(url) и
client.focus() дают возможность перенаправлять и
фокусировать вкладки, контролируя пользовательский интерфейс из
сервис-воркера:
self.addEventListener('notificationclick', event => {
event.waitUntil((async () => {
const allClients = await clients.matchAll({ type: 'window' });
if (allClients.length > 0) {
const client = allClients[0];
client.navigate('/dashboard');
client.focus();
} else {
clients.openWindow('/dashboard');
}
})());
});
Эта техника часто используется для обработки кликов по push-уведомлениям или обновления контента в реальном времени.
Workbox поддерживает skipWaiting() и
clients.claim() для контроля активации нового
сервис-воркера. После активации можно оповестить все вкладки о новой
версии приложения:
self.addEventListener('activate', async event => {
event.waitUntil((async () => {
await clients.claim();
const allClients = await clients.matchAll({ type: 'window' });
allClients.forEach(client => client.postMessage({ type: 'NEW_VERSION_AVAILABLE' }));
})());
});
Такой подход позволяет обеспечить плавное обновление SPA без необходимости закрывать вкладки пользователям.
Clients API позволяет фильтровать клиентов по URL и по типу:
const dashboardClients = await clients.matchAll({
type: 'window',
includeUncontrolled: true
});
const filteredClients = dashboardClients.filter(client => client.url.includes('/dashboard'));
Это полезно для направленной рассылки сообщений только тем вкладкам, которые отображают определённый раздел приложения, минимизируя лишнюю нагрузку на остальные вкладки.
Clients API в сочетании с Workbox обеспечивает мощный
инструмент для управления открытыми вкладками, синхронизации
данных и повышения интерактивности веб-приложений. Важным аспектом
является корректное использование clients.matchAll() и
асинхронных методов, чтобы обеспечить надежную и отзывчивую
работу сервиса в реальном времени.