Service Worker — это скрипт, работающий в фоне браузера независимо от веб-страницы. Он обеспечивает возможности для офлайн-доступа, фоновых синхронизаций, push-уведомлений и управления кэшированием ресурсов. В контексте Riot.js Service Worker можно использовать для ускорения загрузки компонентов, стилей и данных, что особенно важно для одностраничных приложений (SPA).
Service Worker регистрируется через JavaScript и управляется событием
install, которое позволяет подготовить кэширование
необходимых ресурсов:
if ('serviceWorker' in navigator) {
navigator.serviceWorker.register('/service-worker.js')
.then(reg => console.log('Service Worker зарегистрирован', reg))
.catch(err => console.error('Ошибка регистрации Service Worker', err));
}
Файл service-worker.js выполняет ключевые функции по
кэшированию и обработке запросов.
Статические ресурсы — это файлы, которые редко изменяются: HTML-шаблоны, CSS, JavaScript-компоненты Riot.js и изображения. Для их кэширования используется Cache API:
const CACHE_NAME = 'riot-app-v1';
const STATIC_ASSETS = [
'/',
'/index.html',
'/bundle.js',
'/styles.css'
];
self.addEventListener('install', event => {
event.waitUntil(
caches.open(CACHE_NAME)
.then(cache => cache.addAll(STATIC_ASSETS))
);
});
CACHE_NAME — уникальное имя кэша, которое позволяет
управлять версиями.STATIC_ASSETS — массив ресурсов для кэширования во
время установки.Использование event.waitUntil() гарантирует, что Service
Worker не будет считаться установленным, пока кэш не завершит загрузку
всех ресурсов.
Service Worker позволяет перехватывать сетевые запросы через событие
fetch. Это позволяет отдавать ресурсы из кэша или обновлять
их при необходимости:
self.addEventListener('fetch', event => {
event.respondWith(
caches.match(event.request)
.then(cachedResponse => {
if (cachedResponse) {
return cachedResponse;
}
return fetch(event.request)
.then(networkResponse => {
return caches.open(CACHE_NAME)
.then(cache => {
cache.put(event.request, networkResponse.clone());
return networkResponse;
});
});
})
);
});
Особенности работы:
caches.match() проверяет наличие запроса в кэше.networkResponse.clone() необходим, так как поток ответа
можно использовать только один раз. Один экземпляр возвращается
браузеру, другой сохраняется в кэш.Для корректной работы приложения требуется управление версиями кэша. Старые кэши удаляются при активации нового Service Worker:
self.addEventListener('activate', event => {
const allowedCaches = [CACHE_NAME];
event.waitUntil(
caches.keys()
.then(cacheNames => Promise.all(
cacheNames.map(name => {
if (!allowedCaches.includes(name)) {
return caches.delete(name);
}
})
))
);
});
Это позволяет предотвратить переполнение хранилища браузера устаревшими данными и гарантирует, что пользователи получают актуальные версии файлов Riot.js-компонентов.
Для SPA на Riot.js важна работа с динамическими данными. Service Worker позволяет кэшировать ответы от 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))
)
);
}
});
api-cache) для
разделения статических ресурсов и динамических данных.В Riot.js компоненты загружаются динамически и могут содержать CSS и шаблоны. Использование Service Worker позволяет:
bundle.js).Пример динамического запроса компонента с кэшем:
import { component } from 'riot';
fetch('/components/button.riot')
.then(res => res.text())
.then(source => {
caches.open(CACHE_NAME).then(cache => cache.put('/components/button.riot', new Response(source)));
component(source)(document.getElementById('app'));
});
Существуют несколько стратегий кэширования, применимых в Riot.js:
Выбор стратегии зависит от типа ресурсов и потребностей приложения.
Service Worker обеспечивает работу приложения без подключения к
интернету. Основной принцип — подготовка всех критических ресурсов в
кэше на этапе install и обслуживание запросов через
кэш:
self.addEventListener('fetch', event => {
event.respondWith(
caches.match(event.request)
.then(response => response || fetch(event.request))
.catch(() => caches.match('/offline.html'))
);
});
offline.html отображается, если ни кэш, ни сеть не
доступны.
Service Worker в связке с Riot.js позволяет создавать быстрые, надежные и офлайн-способные приложения, улучшая пользовательский опыт и снижая нагрузку на сервер.