Moderní tvorba webových aplikací
O webu

Service Worker – offline web, push notifikace a cache

Service Worker je skript běžící na pozadí prohlížeče, který umožňuje offline režim, push notifikace a pokročilé cachování webových stránek.

7 minut

Service Worker (SW) je JavaScriptový soubor, který prohlížeč spouští na pozadí, odděleně od webové stránky. Funguje jako proxy mezi prohlížečem a sítí – dokáže zachytávat síťové požadavky, cachovat zdroje a umožnit tak webové aplikaci fungovat i offline.

Co Service Worker umí

  • Offline režim – cachování stránek a zdrojů pro použití bez připojení k internetu
  • Push notifikace – příjem oznámení ze serveru, i když je stránka zavřená
  • Zachytávání požadavků – možnost odpovídat na síťové požadavky z cache místo ze sítě
  • Synchronisace na pozadí – odložení akcí, dokud se uživatel znovu nepřipojí
  • Předběžné načítání (precaching) – stažení zdrojů ještě před tím, než je uživatel potřebuje
  • Periodická synchronisace – pravidelná aktualisace dat na pozadí (Periodic Background Sync API)

Service Worker v DevTools

Omezení

  • Nemá přístup k DOM – komunikuje se stránkou přes postMessage
  • Vyžaduje HTTPS (výjimkou je localhost pro vývoj)
  • Je asynchronní – nemůže používat synchronní API jako localStorage (místo toho lze použít IndexedDB nebo Cache API)

Životní cyklus

Service Worker má tři hlavní fáze:

  1. Registrace – stránka zaregistruje SW soubor
  2. Instalace – prohlížeč stáhne a nainstaluje SW, spustí se událost install
  3. Aktivace – SW se aktivuje a převezme kontrolu nad stránkami, spustí se událost activate

Po aktivaci SW naslouchá událostem fetch (síťové požadavky) a push (push notifikace).

Registrace

Registrace se provádí z hlavní stránky. Nejprve je vhodné ověřit, zda prohlížeč SW podporuje:

if ('serviceWorker' in navigator) {
  navigator.serviceWorker.register('/sw.js')
    .then(function (reg) {
      console.log('SW registrován', reg);
    })
    .catch(function (err) {
      console.log('Registrace selhala', err);
    });
}

Cesta /sw.js určuje i scope (rozsah) – SW na /sw.js má kontrolu nad celým webem. SW na /blog/sw.js by kontroloval pouze stránky začínající na /blog/.

Instalace a cachování

Během instalace je vhodné předem uložit klíčové soubory do cache (tzv. pre-caching):

var CACHE_NAME = 'muj-web-v1';
var urlsToCache = [
  '/',
  '/styles/main.css',
  '/scripts/app.js'
];

self.addEventListener('install', function (event) {
  event.waitUntil(
    caches.open(CACHE_NAME)
      .then(function (cache) {
        return cache.addAll(urlsToCache);
      })
  );
});

Zachytávání požadavků

Po aktivaci SW zachytává všechny síťové požadavky stránek ve svém scope. Základní strategie je cache first – nejprve se podívat do cache, a pokud tam zdroj není, stáhnout ze sítě:

self.addEventListener('fetch', function (event) {
  event.respondWith(
    caches.match(event.request)
      .then(function (response) {
        // Nalezeno v cache
        if (response) {
          return response;
        }
        // Stáhnout ze sítě
        return fetch(event.request);
      })
  );
});

Cache a zároveň uložení do cache

Pokročilejší varianta – pokud zdroj není v cache, stáhne ho ze sítě a zároveň uloží do cache pro příště:

self.addEventListener('fetch', function (event) {
  event.respondWith(
    caches.match(event.request)
      .then(function (response) {
        if (response) {
          return response;
        }

        var fetchRequest = event.request.clone();

        return fetch(fetchRequest).then(function (response) {
          if (!response || response.status !== 200) {
            return response;
          }

          var responseToCache = response.clone();

          caches.open(CACHE_NAME)
            .then(function (cache) {
              cache.put(event.request, responseToCache);
            });

          return response;
        });
      })
  );
});

Všimněte si volání .clone() – požadavek i odpověď jsou streamy, které lze přečíst jen jednou. Je potřeba vytvořit kopii pro cache a originál vrátit prohlížeči.

Aktualisace Service Workeru

Prohlížeč při každé návštěvě stránky kontroluje, zda se soubor SW změnil. Pokud ano:

  1. Nový SW se nainstaluje na pozadí
  2. Čeká, dokud starý SW neztratí kontrolu nad všemi stránkami (všechny záložky se zavřou)
  3. Nový SW se aktivuje

V události activate je vhodné smazat staré cache:

self.addEventListener('activate', function (event) {
  event.waitUntil(
    caches.keys().then(function (cacheNames) {
      return Promise.all(
        cacheNames.filter(function (name) {
          return name !== CACHE_NAME;
        }).map(function (name) {
          return caches.delete(name);
        })
      );
    })
  );
});

Push notifikace

Service Worker umí přijímat push notifikace ze serveru i po zavření stránky. Nejprve je potřeba získat od uživatele povolení:

Notification.requestPermission().then(function (permission) {
  if (permission === 'granted') {
    console.log('Notifikace povoleny');
  }
});

V SW pak nasloucháme události push:

self.addEventListener('push', function (event) {
  var title = 'Nová zpráva';
  var options = {
    body: event.data.text(),
    icon: '/images/icon-192.png'
  };

  event.waitUntil(
    self.registration.showNotification(title, options)
  );
});

Ladění

V Chrome DevTools v záložce Application → Service Workers lze:

  • Zobrazit stav registrovaných SW
  • Ručně spustit aktualisaci
  • Odregistrovat SW
  • Simulovat offline režim

Pro vývoj je užitečné zaškrtnout Update on reload, aby se SW aktualisoval při každém obnovení stránky.

Zvažte, jestli SW opravdu potřebujete

Na první pohled Service Worker zní jako skvělá věc – offline režim, cachování, push notifikace. V praxi ale přidává do projektu značnou komplexitu a dost komplikuje vývoj i debugování.

Zvláště používání SW pro cachování dokáže vývojáře pořádně potrápit. Stránka se chová zvláštně, změny se neprojevují, obsah je zastaralý – a než člověka napadne, že za tím stojí Service Worker a že ho stačí odregistrovat, může nad tím strávit hodiny.

Doporučuji proto dobře zvážit, jestli SW na svém webu skutečně potřebujete. Pro většinu běžných webů je to zbytečná zátěž navíc.

Související odkazy

Co si myslíte o tomto článku?

Diskuse

Související články

IndexedDB – klientská database v prohlížeči

IndexedDB je nízkoúrovňové API pro ukládání velkého množství strukturovaných dat na straně klienta, včetně souborů a blobů.

7 minut

Offline stránka v PWA přes ServiceWorker

Jak udělat web fungující offline. A splnit tak požadavky na PWA.

12 minut

Stažení dynamického webu

Jak stáhnout celou webovou stránku a převést ji do statické HTML podoby.

5 minut

Je uživatel online?

Jak zjistit, jestli je uživatel webové aplikace online nebo offline.

5 minut

Novinky e-mailem

Když budu mít něco opravdu zajímavého, můžu vám to poslat e-mailem

Přidej se k 500+ čtenářům
Jen kvalitní obsah
Žádný spam

Web jecas.cz píše Bohumil Jahoda, kontakt
Seznam všech článků · Témata · Zkratky
2013–2026