Что такое Service Worker и чем он отличается от обычного JS

Обычный JavaScript выполняется в главном потоке страницы и имеет доступ к DOM. Service Worker работает в отдельном фоновом потоке — у него нет доступа к DOM, но есть возможность перехватывать все сетевые запросы и управлять кэшем браузера.

Жизненный цикл Service Worker:

  1. Регистрация — страница регистрирует SW через navigator.serviceWorker.register('/sw.js')
  2. Установка — SW устанавливается и может заранее кэшировать статические ресурсы
  3. Активация — SW берёт управление над страницей
  4. Работа — перехватывает запросы через fetch event
// sw.js — базовый пример стратегии "cache first"
self.addEventListener('fetch', event => {
  event.respondWith(
    caches.match(event.request).then(cached => {
      return cached || fetch(event.request);
    })
  );
});

Стратегии кэширования

Service Worker позволяет реализовать разные стратегии для разных типов ресурсов:

Стратегия Логика Применение
Cache First Сначала кэш, потом сеть Статика (CSS, JS, шрифты)
Network First Сначала сеть, при ошибке — кэш HTML-страницы, данные
Stale While Revalidate Возвращает кэш, фоново обновляет Изображения, полустатика
Network Only Всегда сеть, без кэша API персонализации, корзина
Cache Only Только кэш Офлайн-fallback

Service Worker и персонализация: подводные камни

Для e-commerce с персонализацией Service Worker создаёт специфический риск: кэшированный персонализированный ответ. Если API рекомендаций попал в кэш SW с долгим TTL — другой пользователь или следующая сессия получит чужие рекомендации.

Правила для персонализированных данных:

  1. Исключить из кэша все запросы с Authorization или userId параметрами
  2. Network Only стратегия для API рекомендаций, корзины, профиля
  3. Cache Only — только для полностью статических ресурсов
// Пример: исключаем API персонализации из кэширования
self.addEventListener('fetch', event => {
  const url = new URL(event.request.url);

  if (url.pathname.startsWith('/api/personalization/')) {
    // Всегда через сеть — не кэшировать
    event.respondWith(fetch(event.request));
    return;
  }
  // Остальные ресурсы — cache first
  event.respondWith(cacheFirst(event.request));
});

Применение в e-commerce PWA

  • Офлайн-страница — пользователь без интернета видит кастомную страницу, а не ошибку браузера
  • Предзагрузка — SW загружает ресурсы следующей страницы пока пользователь читает текущую
  • Web Push — уведомления о брошенной корзине, снижении цены, новинках
  • Background sync — добавление в список желаний без интернета с синхронизацией при восстановлении связи

Важно: при обновлении сайта (деплой) нужно инвалидировать кэш Service Worker. Пользователи могут продолжать видеть устаревшую версию, пока SW не обновится. Используйте версионированные cache key или вызов skipWaiting() при критичных обновлениях.