Представьте себе веб-страницу, которая работает без интернета, получает push-уведомления, как нативное приложение, и молниеносно загружает контент. Это не магия будущего, а реальность, которую создают Service Workers — революционная технология, превращающая обычные сайты в Progressive Web Apps. В этой статье мы разберемся, как они работают, и рассмотрим практические примеры, которые вы сможете внедрить уже сегодня.
Что такое Service Worker?
Service Worker — это скрипт, который ваш браузер запускает в фоновом режиме, отдельно от веб-страницы. Он действует как прокси-сервер между вашим приложением, сетью и браузером. Его ключевая суперсила — перехватывать сетевые запросы, управлять кешем и обеспечивать работу в офлайн-режиме. В отличие от обычных веб-воркеров, он может работать даже когда вкладка закрыта.
Важно: Service Worker работает только по HTTPS (за исключением localhost для разработки). Это требование безопасности, так как он имеет огромную власть над сетевыми запросами.
Жизненный цикл Service Worker
Понимание жизненного цикла критически важно. Он состоит из нескольких этапов:
- Регистрация: Скрипт регистрируется в браузере с помощью
navigator.serviceWorker.register(). - Установка: Браузер загружает и пытается установить новый SW. Идеальное место для предварительного кеширования критически важных ресурсов.
- Активация: После успешной установки SW активируется. Здесь можно очистить старые кеши.
- Простой (Idle): SW ожидает событий (сетевых запросов, push-сообщений).
- Завершение (Terminated): Браузер может остановить SW для экономии ресурсов.
- Повторный запуск (Fetch/Message): При необходимости SW перезапускается.
Практические примеры Service Workers
Пример 1: Офлайн-страница и базовое кеширование
Самый простой и полезный пример — показать пользователю кастомную страницу, когда сеть недоступна.
// sw.js
self.addEventListener('install', event => {
event.waitUntil(
caches.open('v1').then(cache => {
return cache.addAll([
'/offline.html',
'/styles/main.css',
'/script.js'
]);
})
);
});
self.addEventListener('fetch', event => {
event.respondWith(
fetch(event.request).catch(() => {
return caches.match('/offline.html');
})
);
});
Этот код при установке кеширует ключевые файлы, а при неудачном запросе к сети показывает запасную страницу.
Пример 2: Стратегия «Сеть, затем кеш» (Stale-While-Revalidate)
Идеально для часто обновляемого контента, где важна актуальность (например, лента новостей).
self.addEventListener('fetch', event => {
event.respondWith(
fetch(event.request).then(networkResponse => {
// Клонируем ответ, так как поток можно прочитать только раз
const responseClone = networkResponse.clone();
caches.open('dynamic-cache').then(cache => {
cache.put(event.request, responseClone);
});
return networkResponse;
}).catch(() => {
// Если сеть недоступна, ищем в кеше
return caches.match(event.request);
})
);
});
Сначала запрос идет в сеть, и при успехе ответ обновляет кеш. При ошибке сети — данные берутся из кеша.
Пример 3: Фоновые push-уведомления
Service Worker — единственное место в веб-приложении, где можно обрабатывать push-сообщения, даже когда сайт не открыт.
self.addEventListener('push', event => {
const options = {
body: event.data.text(),
icon: '/icon-192.png',
badge: '/badge.png',
vibrate: [200, 100, 200]
};
event.waitUntil(
self.registration.showNotification('Новое уведомление!', options)
);
});
self.addEventListener('notificationclick', event => {
event.notification.close();
event.waitUntil(
clients.openWindow('https://ваш-сайт.ru/спец-страница')
);
});
Совет по отладке: Используйте вкладку Application в Chrome DevTools. Там вы можете увидеть зарегистрированных Service Workers, принудительно обновить их, имитировать офлайн-режим и просматривать содержимое кешей.
Лучшие практики и подводные камни
- Всегда используйте
event.waitUntil()в жизненно важных событиях (install,activate,push), чтобы браузер знал, когда операция завершена. - Очищайте старые кеши в событии
activate, чтобы не захламлять память пользователя. - Будьте осторожны с кешированием! Не кешируйте HTML-страницы с динамическим контентом без стратегии обновления, иначе пользователь никогда не увидит новые данные.
- Используйте версионирование кешей (например,
cache-v2). Это упрощает управление.
FAQ: Часто задаваемые вопросы
Может ли Service Worker получить доступ к DOM?
Нет, напрямую — нет. Service Worker работает в отдельном контексте. Для взаимодействия с открытыми страницами используется API postMessage().
Как обновить Service Worker?
Браузер автоматически проверяет обновления SW при каждой навигации. Новый SW устанавливается параллельно со старым, но активируется только когда все вкладки со старым SW закроются (если не использовать self.skipWaiting()).
Service Worker «висит» в памяти постоянно?
Нет. Браузеры экономят ресурсы и могут остановить неактивного SW. Он автоматически перезапускается при поступлении событий (например, fetch или push).
Поддерживают ли Service Workers все браузеры?
Подавляющее большинство современных браузеров (Chrome, Firefox, Edge, Safari) поддерживают основные возможности. Всегда проверяйте поддержку с помощью if ('serviceWorker' in navigator).
В чем разница между Service Worker и Web Worker?
Web Worker предназначен для выполнения тяжелых вычислений в фоне, не блокируя основной поток. Service Worker — это специфический тип воркера, созданный именно для управления сетевыми запросами, кешированием и push-уведомлениями.