Управление клиентами через Clients API

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'));

Это полезно для направленной рассылки сообщений только тем вкладкам, которые отображают определённый раздел приложения, минимизируя лишнюю нагрузку на остальные вкладки.

Практические сценарии использования

  1. Push-уведомления: мгновенная рассылка сообщений всем открытым вкладкам.
  2. Реализация “soft update”: уведомление пользователей о новой версии SPA.
  3. Синхронизация состояний: например, обновление корзины или статуса авторизации между вкладками.
  4. Управление навигацией: открытие нужной страницы при взаимодействии с уведомлениями или внешними ссылками.

Clients API в сочетании с Workbox обеспечивает мощный инструмент для управления открытыми вкладками, синхронизации данных и повышения интерактивности веб-приложений. Важным аспектом является корректное использование clients.matchAll() и асинхронных методов, чтобы обеспечить надежную и отзывчивую работу сервиса в реальном времени.