Skip to main content

Service Worker

Service Worker це спеціальний фоновий скрипт, який браузер запускає між сторінкою і мережею: він може перехоплювати мережеві запити, кешувати відповіді та реагувати на події (fetch, push, sync) навіть тоді, коли вкладку закрито. Простіше кажучи, це проксі-сервер усередині браузера, яким ви керуєте з JavaScript.

Теорія

TL;DR

  • Service Worker це окремий потік виконання, ізольований від сторінки: без window і без document.
  • Він стоїть між сторінкою і мережею і сам вирішує, віддати відповідь з кешу чи піти в мережу.
  • Життєвий цикл: реєстрація, install, activate, робота за подіями, вивантаження.
  • Основні можливості: перехоплення fetch, Cache API, push-сповіщення, background sync, periodic sync.
  • Працює лише через HTTPS (виняток: localhost) і має квоти на розмір кешу.
  • Це технологічна основа PWA: офлайн-доступ, миттєве завантаження, сповіщення без відкритої вкладки.

Швидкий приклад

sw.js:

javascript
self.addEventListener('install', (event) => { console.log('Service worker is installing'); event.waitUntil( caches.open('v1').then((cache) => cache.addAll([ '/', '/index.html', '/styles.css', '/app.js' ])) ); }); self.addEventListener('activate', () => { console.log('Service worker is active'); }); self.addEventListener('fetch', (event) => { console.log('Intercepted request:', event.request.url); event.respondWith( caches.match(event.request).then((response) => { return response || fetch(event.request); // from cache or from the network }) ); });

Реєстрація в основному коді сторінки:

javascript
if ('serviceWorker' in navigator) { navigator.serviceWorker.register('/sw.js') .then(() => console.log('Service worker registered')) .catch(console.error); }

Цей воркер зберігає файли в кеш під час встановлення, перехоплює всі запити і віддає кешовану відповідь, а якщо її немає, іде в мережу.

Архітектура і життєвий цикл

Схематично Service Worker стоїть посередині:

text
Internet ^ | fetch request v +-----------------------+ | Service Worker | proxy between the page and the network | - intercept fetch | | - serve from cache | | - push notifications | | - background sync | +-----------------------+ ^ | +-----------------------+ | Page (browser tab)| +-----------------------+

Життєвий цикл складається з п'яти кроків:

  1. Реєстрація. Сторінка повідомляє браузеру, де лежить файл воркера: navigator.serviceWorker.register('/sw.js').
  2. Встановлення (install). Браузер завантажує скрипт і встановлює його один раз. Тут зазвичай наповнюють кеш через event.waitUntil(...).
  3. Активація (activate). Старі версії воркера знімаються з реєстрації, новий стає активним. Тут прибирають застарілі кеші.
  4. Робота (fetch / push / sync). Після активації воркер слухає події: fetch перехоплює запити, push приймає сповіщення, sync виконує фонові задачі.
  5. Вивантаження (idle / terminate). Коли воркер не потрібен, браузер вивантажує його з пам'яті і «будить» знову на наступній події.

Що вміє Service Worker

МожливістьЩо робить
Fetch interceptionПерехоплює і контролює всі мережеві запити сторінки
Caching APIЗберігає файли та відповіді в кеші, це дає роботу офлайн
Background syncВиконує відкладені задачі, коли мережа відновиться
Push notificationsОтримує push-повідомлення від сервера і показує їх
Offline-firstДозволяє застосунку працювати без інтернету
Periodic syncВиконує дії за розкладом
Proxy layerДодає контроль над запитами і відповідями

Офлайн-кеш і fallback-сторінка

Найпростіший офлайн-сценарій: спробувати мережу, а при помилці віддати заздалегідь закешовану сторінку.

javascript
self.addEventListener('fetch', (event) => { event.respondWith( fetch(event.request).catch(() => caches.match('/offline.html')) ); });

Якщо інтернету немає, користувач бачить /offline.html замість помилки браузера: застосунок не «падає», а показує повідомлення «Ви офлайн».

Під час активації варто чистити застарілі версії кешу, інакше квота швидко закінчиться:

javascript
self.addEventListener('activate', (event) => { event.waitUntil( caches.keys().then((keys) => Promise.all( keys.filter((key) => key !== 'v1').map((key) => caches.delete(key)) )) ); });

Push-сповіщення і background sync

Push працює навіть із закритою вкладкою: браузер «будить» Service Worker, щоб той обробив подію.

javascript
self.addEventListener('push', (event) => { const data = event.data.json(); event.waitUntil( self.registration.showNotification(data.title, { body: data.body, icon: '/icon.png' }) ); });

Background sync дає змогу відкласти задачу до появи мережі:

javascript
self.addEventListener('sync', (event) => { if (event.tag === 'sendFormData') { event.waitUntil(sendDataToServer()); } });

Типовий сценарій: користувач офлайн, дані форми лягають в IndexedDB, а коли мережа відновиться, Service Worker сам відправить їх на сервер.

Обмеження і де застосовують

ОсобливістьОпис
Ізольований від DOMНемає window і document, зі сторінкою спілкується через postMessage
Тільки HTTPSПрацює лише на захищених доменах, виняток становить localhost
Обмежений обсяг сховищаБраузер дає квоту на кеш і може очистити його
Автоматично вивантажується«Прокидається» за подіями, не живе постійно

Де це реально використовують:

  • PWA (Progressive Web Apps): офлайн-доступ, «додати на екран», миттєве завантаження.
  • Новини і чати: push-сповіщення без відкритої вкладки.
  • Ігри та офлайн-режими: попереднє завантаження ассетів і даних у кеш.
  • Веб-сервіси: кешування відповідей API і економія трафіку.

Підсумок одним поглядом:

ПараметрОпис
ТипФоновий JS-потік між сторінкою і мережею
Головні функціїПерехоплення запитів, кеш, push, background sync
Працює при закритій вкладціТак
Доступ до DOMНі
Потребує HTTPSТак
Основне застосуванняPWA, офлайн-режим, сповіщення

Типові помилки

  • Думати, що Service Worker це те саме, що Web Worker. Web Worker рахує щось у фоні для однієї сторінки, Service Worker керує мережею для всіх вкладок свого scope і живе довше за них.
  • Звертатися до document або window усередині воркера. Їх там немає, обмін даними йде через postMessage і clients.
  • Забути про очищення старих кешів в activate. Версії накопичуються, і браузер зрештою знесе весь кеш за квотою.
  • Кешувати все підряд, зокрема відповіді API з авторизацією. Користувач може побачити чужі або застарілі дані.
  • Очікувати, що новий воркер підхопиться одразу. Після оновлення він чекає стану waiting, поки не закриють старі вкладки, якщо не викликати skipWaiting() і clients.claim().
  • Не передбачити відкат. Помилковий fetch-обробник може «зламати» сайт для вже встановлених користувачів, тому потрібен шлях до розреєстрації воркера.

Коротка відповідь

Для співбесіди
Premium

Коротка відповідь допоможе вам впевнено відповідати на цю тему під час співбесіди.