Запропонувати правкуПокращити цю статтюДопрацюйте відповідь до «Service Worker». Ваші зміни проходять модерацію перед публікацією.Потрібне підтвердженняКонтентЩо ви змінюєте🇺🇸EN🇺🇦UAПереглядЗаголовок (UA)Коротка відповідь (UA)**Service Worker це окремий фоновий скрипт, який браузер запускає між сторінкою і мережею: він перехоплює запити через подію `fetch`, віддає відповіді з кешу, показує push-сповіщення і виконує відкладені задачі через background sync навіть тоді, коли вкладку закрито.** Він не має доступу до DOM, працює лише через HTTPS (або на localhost), живе за подіями і вивантажується з пам'яті, коли простоює. Це основа PWA і офлайн-режиму. ```javascript self.addEventListener('fetch', (event) => { // from cache first, otherwise go to the network event.respondWith( caches.match(event.request).then((cached) => cached || fetch(event.request)) ); }); ``` **Ключове:** Service Worker це програмований проксі всередині браузера, який керує мережею і кешем застосунку.Показується над повною відповіддю для швидкого нагадування.Відповідь (UA)Зображення**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`-обробник може «зламати» сайт для вже встановлених користувачів, тому потрібен шлях до розреєстрації воркера.Для рев’юераПримітка для модератора (необов’язково)Бачить лише модератор. Прискорює рев’ю.