Прослушивание обновлений на стороне клиента

Workbox предоставляет мощные инструменты для управления кэшированием и обновлениями сервис-воркеров, включая возможность отслеживания появления новых версий приложения на стороне клиента. Контроль за обновлениями позволяет реализовать сценарии «мягкого» обновления, уведомления пользователя о доступных обновлениях и автоматическое применение новых ресурсов.

Регистрация сервис-воркера

Для начала необходимо корректно зарегистрировать сервис-воркер с использованием Workbox. Пример регистрации с обработкой событий обновления:

if ('serviceWorker' in navigator) {
  window.addEventListener('load', () => {
    navigator.serviceWorker.register('/sw.js').then(registration => {

      // Проверка наличия нового сервис-воркера
      registration.onupdatefo und = () => {
        const newWorker = registration.installing;
        newWorker.onstatecha nge = () => {
          if (newWorker.state === 'installed') {
            if (navigator.serviceWorker.controller) {
              console.log('Доступна новая версия приложения');
            } else {
              console.log('Контент кэширован впервые');
            }
          }
        };
      };

    }).catch(error => {
      console.error('Ошибка при регистрации сервис-воркера:', error);
    });
  });
}

В этом коде важно различать состояния installed и наличие navigator.serviceWorker.controller. Если контроллер уже существует, это означает, что в браузере есть активная версия приложения, и новая версия была установлена, но еще не активирована.

Прослушивание сообщений от сервис-воркера

Workbox позволяет сервис-воркеру отправлять сообщения клиенту. Для этого используется метод postMessage в воркере и navigator.serviceWorker.addEventListener('message', ...) на клиенте.

Пример отправки сообщения из сервис-воркера при обновлении:

self.addEventListener('install', event => {
  self.skipWaiting();
});

self.addEventListener('activate', event => {
  event.waitUntil(
    clients.claim().then(() => {
      self.clients.matchAll().then(clients => {
        clients.forEach(client => client.postMessage({ type: 'NEW_VERSION_AVAILABLE' }));
      });
    })
  );
});

На стороне клиента прослушивание сообщений выглядит так:

navigator.serviceWorker.addEventListener('message', event => {
  if (event.data && event.data.type === 'NEW_VERSION_AVAILABLE') {
    console.log('Обнаружена новая версия приложения');
    // Можно инициировать уведомление или автоматическое обновление
  }
});

Автоматическое обновление страниц

Для немедленного применения новой версии можно использовать метод skipWaiting() в сервис-воркере и команду clients.claim() при активации. Однако необходимо контролировать момент, когда это произойдет, чтобы не нарушить текущую сессию пользователя. Обычно применяется комбинация:

  1. При обнаружении нового воркера – уведомление пользователя.
  2. По подтверждению – отправка команды на активацию и перезагрузку страницы.
function promptUserToUpdate(registration) {
  if (confirm("Доступна новая версия приложения. Обновить сейчас?")) {
    if (registration.waiting) {
      registration.waiting.postMessage({ type: 'SKIP_WAITING' });
    }
  }
}

navigator.serviceWorker.addEventListener('controllerchange', () => {
  window.location.reload();
});

В сервис-воркере:

self.addEventListener('message', event => {
  if (event.data && event.data.type === 'SKIP_WAITING') {
    self.skipWaiting();
  }
});

Отслеживание состояния загрузки ресурсов

Workbox предоставляет события жизненного цикла для стратегий кэширования, которые можно использовать для отслеживания прогресса обновления отдельных ресурсов. Например, с использованием Workbox.precaching:

import { precacheAndRoute, precache } from 'workbox-precaching';

precacheAndRoute(self.__WB_MANIFEST);

self.addEventListener('message', event => {
  if (event.data && event.data.type === 'CHECK_UPDATES') {
    precache.getCacheKeys().then(keys => {
      console.log('Кэшированные ресурсы:', keys);
    });
  }
});

Используя precacheAndRoute, можно контролировать установку, активацию и проверку обновлений для конкретных файлов манифеста. Это особенно важно для крупных приложений, где кэширование каждого ресурса имеет значение для корректного обновления.

Практические рекомендации

  • Регулярная проверка обновлений: Запуск функции проверки новых версий при загрузке приложения или через определенные интервалы позволяет поддерживать актуальность контента.
  • Управление пользователем: Предоставление пользователю выбора обновления предотвращает неожиданное прерывание работы приложения.
  • Логирование событий: Отслеживание состояния воркера (installing, installed, activating, activated) помогает диагностировать проблемы с кэшированием и обновлениями.
  • Использование стратегий Workbox: Правильная комбинация стратегий (например, NetworkFirst для данных и CacheFirst для статических ресурсов) минимизирует задержки при обновлении контента.

Итоговое управление обновлениями

Комбинирование отслеживания состояния сервис-воркера, прослушивания сообщений и уведомления пользователя позволяет реализовать гибкую систему обновления, которая:

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

Эта модель является стандартом для современных PWA и полностью интегрируется с возможностями Workbox по управлению кэшом и жизненным циклом сервис-воркера.