Service Workers в контексте Preact

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

Основы работы Service Worker

Service Worker регистрируется через navigator.serviceWorker.register() и работает независимо от жизненного цикла веб-страницы. Основные события, на которые реагирует Service Worker:

  • install — установка Service Worker, идеальное место для кэширования статических ресурсов.
  • activate — активация нового Service Worker и очистка устаревших кэшей.
  • fetch — перехват сетевых запросов и управление ими (например, отдача ресурсов из кэша).

Простейший пример регистрации Service Worker:

if ('serviceWorker' in navigator) {
  navigator.serviceWorker.register('/service-worker.js')
    .then(registration => {
      console.log('Service Worker зарегистрирован с областью:', registration.scope);
    })
    .catch(error => {
      console.error('Ошибка регистрации Service Worker:', error);
    });
}

Интеграция с Preact

Preact, будучи легковесным фреймворком, не накладывает специфических ограничений на работу с Service Worker. Основные подходы:

  1. Кэширование статических ресурсов приложения В Preact-приложениях важно кэшировать сборку (bundle.js, index.html, style.css) для оффлайн-доступа. Обычно используется кэш с версионированием:
const CACHE_NAME = 'preact-app-v1';
const urlsToCache = [
  '/',
  '/index.html',
  '/bundle.js',
  '/style.css'
];

self.addEventListener('install', event => {
  event.waitUntil(
    caches.open(CACHE_NAME)
      .then(cache => cache.addAll(urlsToCache))
  );
});

self.addEventListener('activate', event => {
  event.waitUntil(
    caches.keys().then(cacheNames =>
      Promise.all(
        cacheNames.filter(name => name !== CACHE_NAME)
                  .map(name => caches.delete(name))
      )
    )
  );
});
  1. Перехват запросов через fetch Для динамического контента или API-запросов Service Worker может отдавать кэшированные данные или обращаться к сети, используя стратегию Cache First или Network First:
self.addEventListener('fetch', event => {
  event.respondWith(
    caches.match(event.request)
      .then(response => response || fetch(event.request))
  );
});

Работа с оффлайн-режимом

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

self.addEventListener('fetch', event => {
  if (event.request.url.includes('/api/')) {
    event.respondWith(
      fetch(event.request)
        .then(response => {
          return caches.open('api-cache').then(cache => {
            cache.put(event.request, response.clone());
            return response;
          });
        })
        .catch(() => caches.match(event.request))
    );
  }
});

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

Управление обновлениями Service Worker

Preact-приложения часто требуют своевременного обновления контента. Service Worker позволяет контролировать этот процесс через сообщения и жизненный цикл:

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

В основном приложении можно отправлять сообщение для немедленной активации нового Service Worker:

if (navigator.serviceWorker.controller) {
  navigator.serviceWorker.controller.postMessage('skipWaiting');
}

Интеграция с Preact CLI

При использовании Preact CLI Service Worker часто генерируется автоматически через Workbox. Файл preact.config.js позволяет настраивать стратегию кэширования, добавлять маршруты, статические файлы и стратегию обновлений. Пример конфигурации Workbox:

export default (config, env, helpers) => {
  if (env.production) {
    config.plugins.push(
      new WorkboxPlugin.GenerateSW({
        clientsClaim: true,
        skipWaiting: true,
        runtimeCaching: [{
          urlPattern: /\/api\//,
          handler: 'NetworkFirst'
        }]
      })
    );
  }
};

Ключевые моменты при работе с Preact и Service Worker

  • Service Worker всегда работает отдельно от приложения, поэтому важно обрабатывать сообщения между приложением и SW через postMessage.
  • Статические ресурсы лучше кэшировать на стадии установки, динамические данные — при перехвате fetch.
  • Обновления Service Worker необходимо контролировать, чтобы избежать конфликтов версий и устаревших кэшей.
  • Для приложений, создаваемых через Preact CLI, Workbox облегчает конфигурацию и обеспечивает оптимизированное кэширование.

Service Worker позволяет Preact-приложениям работать быстрее, потреблять меньше сетевых ресурсов и поддерживать оффлайн-режим без сложной логики на стороне фронтенда. Правильная архитектура кэширования и управления жизненным циклом SW повышает производительность и стабильность приложения.