Поведение при обновлении Service Worker

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

Когда Service Worker обновляется, браузер проходит несколько этапов: скачивание нового скрипта, установка, активация и управление клиентскими страницами. sw-precache предоставляет механизмы для тонкой настройки этого процесса.


Механизм установки и активации

Установка (install) – это этап, на котором новый Service Worker получает возможность кэшировать указанные ресурсы. В sw-precache это реализуется через массив precacheConfig, содержащий пары URL и revision:

self.__precacheManifest = [
  { url: '/index.html', revision: '1234abcd' },
  { url: '/main.js', revision: '5678efgh' }
];
  • url — путь к ресурсу, который нужно кэшировать.
  • revision — уникальный хеш, который меняется при изменении файла.

Если revision не изменился, Service Worker понимает, что ресурс не требует обновления, что предотвращает лишнюю загрузку данных.

Активация (activate) — этап, на котором старый Service Worker заменяется новым. sw-precache автоматически удаляет устаревшие кэшированные ресурсы, оставляя только актуальные. Этот процесс основан на сравнении текущего и предыдущего precacheConfig.


Стратегии обновления контента

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

  1. Cache-first Сначала возвращается кэшированный ресурс, только затем выполняется запрос к сети при отсутствии нужного файла. Применяется для статических ресурсов, таких как CSS, JS и шрифты.

  2. Network-first Приоритет отдаётся сети, кэш используется только как резерв. Подходит для данных, которые часто обновляются, например, JSON с динамическим содержимым.

  3. Stale-while-revalidate Сначала отдаётся кэшированный ресурс, одновременно загружая новую версию из сети и обновляя кэш. Позволяет обеспечить мгновенную загрузку страниц без устаревших данных.


Управление устаревшими кэшами

При каждом обновлении Service Worker sw-precache создает новый кэш с уникальным именем, включающим хеш ревизий файлов. Старые кэши автоматически удаляются в фазе activate, что гарантирует:

  • отсутствие накопления устаревших данных;
  • корректное использование новых версий ресурсов;
  • минимизацию конфликтов между старым и новым кодом.
self.addEventListener('activate', event => {
  const currentCaches = [CACHE_NAME];
  event.waitUntil(
    caches.keys().then(cacheNames => {
      return Promise.all(
        cacheNames.map(cacheName => {
          if (!currentCaches.includes(cacheName)) {
            return caches.delete(cacheName);
          }
        })
      );
    })
  );
});

Управление моментом активации

sw-precache по умолчанию использует поведение wait until all clients are closed. Это значит, что новый Service Worker будет ожидать, пока все вкладки с приложением, управляемым старым Service Worker, не закроются. После этого новый активируется и начинает обслуживать клиентов.

Для более агрессивного обновления можно использовать метод skipWaiting():

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

Это заставляет новый Service Worker активироваться сразу после установки, минуя ожидание закрытия вкладок.


Обновление динамических ресурсов

sw-precache генерирует статические списки для кэширования, но иногда необходимо обновлять динамические данные. Для этого используется комбинация sw-precache с runtime-кэшированием:

workbox.routing.registerRoute(
  /\/api\/.*\/*.json/,
  new workbox.strategies.NetworkFirst({
    cacheName: 'api-cache',
    networkTimeoutSeconds: 5,
    plugins: [
      new workbox.expiration.ExpirationPlugin({ maxEntries: 50, maxAgeSeconds: 86400 })
    ]
  })
);

Это позволяет:

  • получать новые данные при их наличии в сети;
  • использовать кэш как резерв;
  • автоматически очищать устаревшие данные.

Отслеживание новых версий Service Worker

Для уведомления приложения о наличии новой версии Service Worker sw-precache позволяет использовать событие controllerchange на клиентской странице:

navigator.serviceWorker.addEventListener('controllerchange', () => {
  console.log('Новая версия Service Worker активирована');
});

Таким образом, приложение может, например, предложить пользователю обновить страницу, чтобы применить изменения немедленно.


Ключевые рекомендации при обновлении Service Worker

  • Использовать уникальные revision для всех статических файлов, чтобы гарантировать обновление кэша при изменении контента.
  • Применять skipWaiting() с осторожностью: мгновенная активация может прервать работу активных вкладок.
  • Комбинировать pre-caching для статических ресурсов с runtime-кэшированием для динамического контента.
  • Следить за размером кэшей и автоматически удалять устаревшие записи.
  • Информировать пользователей о новой версии, если это критично для функциональности приложения.

Эффективная организация обновления Service Worker с sw-precache позволяет поддерживать актуальность ресурсов, минимизировать задержки и обеспечить стабильную работу веб-приложения.