Service Workers в Polymer

Service Workers представляют собой скрипты, работающие в фоновом режиме браузера, которые позволяют управлять кэшированием ресурсов, обработкой сетевых запросов и уведомлениями без вмешательства основного потока страницы. В контексте Polymer их использование особенно актуально для создания прогрессивных веб-приложений (PWA), обеспечивая оффлайн-режим и ускоряя загрузку компонентов.

Регистрация Service Worker

Для работы Service Worker сначала необходимо его зарегистрировать. В Polymer это делается обычно в корневом компоненте приложения или в основном скрипте:

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

Ключевые моменты:

  • Проверка if ('serviceWorker' in navigator) необходима для поддержки браузеров, где Service Worker не реализован.
  • registration.scope определяет область действия Service Worker — все запросы в пределах этой области будут перехватываться.

Структура файла Service Worker

Файл service-worker.js должен располагаться в корне приложения или в той же директории, что и регистрация, чтобы корректно работать с областью видимости. Основные события Service Worker:

  • install — событие установки, где обычно происходит предзагрузка и кэширование ресурсов.
  • activate — событие активации, часто используется для очистки старых кэшей.
  • fetch — событие перехвата сетевых запросов, позволяет отдавать кэшированные ресурсы или реализовать стратегии «сеть-кэш» и «кэш-сеть».

Пример базового Service Worker с кэшированием ресурсов:

const CACHE_NAME = 'polymer-app-cache-v1';
const urlsToCache = [
  '/',
  '/index.html',
  '/src/my-element.js',
  '/styles/main.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.map(cache => {
          if (cache !== CACHE_NAME) {
            return caches.delete(cache);
          }
        })
      )
    )
  );
});

self.addEventListener('fetch', event => {
  event.respondWith(
    caches.match(event.request)
      .then(response => response || fetch(event.request))
  );
});

Важные аспекты:

  • Использование event.waitUntil() гарантирует завершение асинхронных операций до окончания события.
  • caches.match(event.request) ищет ресурс в кэше перед запросом к сети.
  • Механизм очистки старых кэшей через activate позволяет поддерживать актуальные версии ресурсов без конфликтов.

Интеграция с Polymer-компонентами

Polymer-компоненты могут поставляться как отдельные модули JavaScript. Service Worker обеспечивает их оффлайн-доступ и ускорение загрузки за счет кэширования:

urlsToCache.push('/bower_components/polymer/polymer-element.js');
urlsToCache.push('/src/components/my-button.js');

При этом, при изменении версии компонента необходимо обновлять кэш. Для этого используют динамическое управление версиями CACHE_NAME, например:

const CACHE_NAME = `polymer-app-cache-${new Date().getTime()}`;

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

  1. Cache First (Кэш в приоритете) Сначала проверяется кэш, если ресурс найден — возвращается он, иначе запрос идет в сеть.
  2. Network First (Сеть в приоритете) Сначала идет сетевой запрос, если он неуспешен — отдаётся кэш.
  3. Stale-While-Revalidate (Устаревший пока обновляется) Возвращается кэш сразу, но параллельно идет запрос в сеть для обновления кэша.

Пример стратегии Stale-While-Revalidate:

self.addEventListener('fetch', event => {
  event.respondWith(
    caches.open(CACHE_NAME).then(cache => 
      cache.match(event.request).then(cachedResponse => {
        const networkFetch = fetch(event.request).then(networkResponse => {
          cache.put(event.request, networkResponse.clone());
          return networkResponse;
        });
        return cachedResponse || networkFetch;
      })
    )
  );
});

Использование Service Worker для оффлайн-поддержки

Оффлайн-функциональность в Polymer часто комбинируется с <app-route> и <app-shell> архитектурой. В таких приложениях Service Worker кэширует статические ресурсы, а динамический контент может быть подгружен через API с fallback на локальное хранилище, например IndexedDB.

// Пример кэширования ответов API
self.addEventListener('fetch', event => {
  if (event.request.url.includes('/api/')) {
    event.respondWith(
      caches.open('api-cache').then(cache =>
        fetch(event.request)
          .then(response => {
            cache.put(event.request, response.clone());
            return response;
          })
          .catch(() => cache.match(event.request))
      )
    );
  }
});

Обновление Service Worker

Для автоматического обновления Service Worker применяют стратегию «skipWaiting» и «clients.claim»:

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

self.addEventListener('activate', event => {
  clients.claim();
});

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


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