Workbox и Web Push-уведомления

Библиотека Workbox предоставляет удобный интерфейс для построения сервис-воркеров в приложениях на JavaScript. Она позволяет легко реализовывать стратегии кэширования, управление ресурсами и оффлайн-поддержку. Основные возможности Workbox включают:

  • Предзагрузка ресурсов (precache) для гарантированного доступа к критически важным файлам.
  • Рунтайм-кэширование (runtime caching) для динамических запросов.
  • Стратегии кэширования: CacheFirst, NetworkFirst, StaleWhileRevalidate, NetworkOnly и CacheOnly.
  • Интеграция с инструментами сборки (Webpack, Rollup) через плагины Workbox.

Пример базового сервис-воркера с предзагрузкой статических файлов:

import { precacheAndRoute } from 'workbox-precaching';

precacheAndRoute([
  { url: '/index.html', revision: '1234' },
  { url: '/styles.css', revision: '1234' },
  { url: '/app.js', revision: '1234' },
]);

Runtime caching и стратегии

Для динамического кэширования запросов Workbox предоставляет удобный метод registerRoute. Важно понимать различия стратегий:

  • CacheFirst — сначала проверяется кэш, если ресурса нет, выполняется запрос в сеть. Подходит для статических ресурсов, редко обновляемых.
  • NetworkFirst — сначала запрос в сеть, если не удалось, используется кэш. Идеально для данных, которые должны быть актуальными.
  • StaleWhileRevalidate — отдаёт кэш сразу, параллельно обновляя его из сети. Оптимальный вариант для контента, который часто обновляется, но может временно отображать устаревшие данные.

Пример:

import { registerRoute } from 'workbox-routing';
import { StaleWhileRevalidate } from 'workbox-strategies';

registerRoute(
  ({ request }) => request.destination === 'image',
  new StaleWhileRevalidate({
    cacheName: 'images-cache',
    plugins: [
      // Ограничение по количеству и сроку хранения
    ],
  })
);

Интеграция с Web Push-уведомлениями

Web Push API в сочетании с Workbox позволяет получать уведомления даже при закрытой вкладке браузера. Основные шаги:

  1. Регистрация сервис-воркера:
if ('serviceWorker' in navigator) {
  navigator.serviceWorker.register('/sw.js')
    .then(reg => console.log('SW зарегистрирован', reg))
    .catch(err => console.error('Ошибка регистрации SW', err));
}
  1. Подписка на push-уведомления:
const swReg = await navigator.serviceWorker.ready;
const subscription = await swReg.pushManager.subscribe({
  userVisibleOnly: true,
  applicationServerKey: urlBase64ToUint8Array('<PUBLIC_VAPID_KEY>')
});
  1. Обработка входящих уведомлений в сервис-воркере:
self.addEventListener('push', event => {
  const data = event.data.json();
  const options = {
    body: data.body,
    icon: '/icon.png',
    badge: '/badge.png',
    data: { url: data.url }
  };
  event.waitUntil(
    self.registration.showNotification(data.title, options)
  );
});

self.addEventListener('notificationclick', event => {
  event.notification.close();
  event.waitUntil(
    clients.matchAll({ type: 'window' }).then(windowClients => {
      for (let client of windowClients) {
        if (client.url === event.notification.data.url && 'focus' in client) {
          return client.focus();
        }
      }
      if (clients.openWindow) {
        return clients.openWindow(event.notification.data.url);
      }
    })
  );
});

Интеграция Workbox с push-уведомлениями

Workbox не предоставляет прямого API для push, но сервис-воркер, созданный через Workbox, полностью совместим с Web Push. Важно учитывать следующие моменты:

  • Разделение логики кэширования и push-уведомлений. Workbox отвечает за кэш, а push-события обрабатываются стандартными событиями push и notificationclick.
  • Использование precacheAndRoute для критичных ресурсов уведомлений (иконки, шрифты, изображения).
  • Оптимизация кэширования данных уведомлений через runtime caching, если уведомления содержат динамический контент (например, миниатюры или аватары пользователей).

Пример совместной настройки:

import { precacheAndRoute } from 'workbox-precaching';
import { registerRoute } from 'workbox-routing';
import { NetworkFirst } from 'workbox-strategies';

precacheAndRoute(self.__WB_MANIFEST);

registerRoute(
  ({ url }) => url.pathname.startsWith('/api/notifications'),
  new NetworkFirst({ cacheName: 'notifications-cache' })
);

self.addEventListener('push', event => {
  const data = event.data.json();
  event.waitUntil(
    self.registration.showNotification(data.title, {
      body: data.body,
      icon: '/icon.png',
      badge: '/badge.png',
    })
  );
});

Лучшие практики

  • Версионирование кэша: использовать ревизии файлов для предотвращения устаревших данных.
  • Минимизация нагрузки сети: использовать стратегии StaleWhileRevalidate и CacheFirst для часто используемых ресурсов.
  • Обработка ошибок: предусматривать fallback-контент, чтобы уведомления корректно отображались даже при проблемах сети.
  • Оптимизация push payload: отправлять минимальные данные, а дополнительную информацию подгружать через runtime caching.

Эти подходы обеспечивают быстрый отклик приложения, надежное кэширование и корректную работу push-уведомлений при любых условиях сети.