Service Workers представляют собой скрипты, работающие в фоновом режиме браузера, которые позволяют управлять кэшированием ресурсов, обработкой сетевых запросов и уведомлениями без вмешательства основного потока страницы. В контексте Polymer их использование особенно актуально для создания прогрессивных веб-приложений (PWA), обеспечивая оффлайн-режим и ускоряя загрузку компонентов.
Для работы 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.js должен располагаться в корне
приложения или в той же директории, что и регистрация, чтобы корректно
работать с областью видимости. Основные события Service Worker:
Пример базового 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-компоненты могут поставляться как отдельные модули 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()}`;
Пример стратегии 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;
})
)
);
});
Оффлайн-функциональность в 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 применяют стратегию «skipWaiting» и «clients.claim»:
self.addEventListener('install', event => {
self.skipWaiting();
});
self.addEventListener('activate', event => {
clients.claim();
});
Это позволяет новой версии Service Worker сразу взять управление страницами, минуя стандартное ожидание закрытия всех вкладок.
Polymer и Service Workers создают мощную комбинацию для построения быстрых, оффлайн-доступных веб-приложений. Кэширование компонентов, управление версиями и гибкие стратегии обработки запросов обеспечивают высокую производительность и удобство работы с приложением в любых условиях сети.