sequenceDiagram
participant B as 🗔 Browser
participant X
B->X: HTTP requests, compute, DOM changes ...
sequenceDiagram
participant B as 🗔 Browser
participant W as 📃 Worker
B->>W: create
sequenceDiagram
participant B as 🗔 Browser
participant W as 📃 Worker
B->>W: create
loop events
W--xB: message
B--xW:
end
All run background scripts independently of any UI
A service worker acts as a proxy between the browser (your web application) and the network
Main usages
graph LR
B("🗔") --> S("📃")
S -.- N("☁")
style B fill:none,stroke:none
style S fill:none,stroke:none
style N fill:none,stroke:none
graph RL
N("🗨") --> S("📃")
S -.- B("🗔")
style B fill:none,stroke:none
style S fill:none,stroke:none
style N fill:none,stroke:none
support: chrome, mozilla, android, opera, edge, safari
support: chrome, mozilla, android, opera, edge (development), safari (development)
document
, nor window
support: chrome, mozilla, android, opera, edge (development), safari (development)
main.js
if (navigator.serviceWorker) navigator.serviceWorker .register('/service-worker.js', { scope: '/' }) .then(registration => registration.state)
Multiple Service Workers must register distinct scopes
support: chrome, mozilla, android, opera, edge (development), safari (development)
service-worker.js
self.addEventListener('install', event => event.waitUntil(/* ready to activate */))
graph LR
P["🗔 page"] -. register .-> I("⚙ install")
I --> A("✔ activate")
I --> E("⚠ error")
style P fill:white
style I fill:white,stroke:#41b6e8
style A fill:white,stroke:green
style E fill:white,stroke:red
support: chrome, mozilla, android, opera, edge (development), safari (development)
install
event handlergraph LR
P["🗔 page"] -. in scope .-> A("✔ activate")
A -. control .-> P
click P callback "in the Service Worker Scope"
style P fill:white,stroke:lightgrey
style A fill:white,stroke:green
support: chrome, mozilla, android, opera, edge (development), safari (development)
New Service Worker will wait deactivation of the old one before it activates
graph LR
subgraph Old Service Worker
O("✔ activate") --> D("☠ deactivate")
end
subgraph New Service Worker
O("✔ activate") -. updatefound .-> I("⚙ install")
I -. waiting .-> A("✔ activate")
end
style O fill:white,stroke:lightgrey
style D fill:white,stroke:red
style I fill:white,stroke:#41b6e8
style A fill:white,stroke:green
Main functional events
graph LR
A("✔ Activated") --> D{"⌛ Idle"}
D --> F("⚙ Handle event")
F --> D
D --> T["☠ Terminated"]
T --> F
style A fill:white,stroke:green
style D fill:white
style F fill:white,stroke:#41b6e8
style T fill:white,stroke:red
Service worker may terminate at any time!
You cannot rely on global state within a service worker
control
the main Threadsupport: chrome, mozilla, android, opera, edge (development), safari (development)
service-worker.js
const CACHE = 'my-awsome-pwa',const FILES = ['/', '/styles.css', '/script.js']self.addEventListener('install', event => event.waitUntil( caches.open(CACHE) .then(cache => cache.addAll(FILES)) ))
support: chrome, mozilla, android, opera, edge (development), safari (development)
service-worker.js
self.addEventListener('fetch', event => event.respondWith( caches.match(event.request) .then(response => response || fetch(event.request)) ))
support: chrome, mozilla, android, opera, edge (development), safari (development)
main.js
const registration = await navigator.serviceWorker.readyconst push = await registration.pushManager.subscribe()sendToBackend(push.endpoint)
manifest.json
(chrome only)
{ ..., "gcm_sender_id": "<Your Sender ID Here>" }
sequenceDiagram
participant B as 🗔 Browser
participant W as 📃 Service Worker
participant S as ➡ Push Server
B->>W: register
activate B
activate W
W--xB: message
deactivate W
B--xW: fetch
activate W
deactivate W
deactivate B
S--xW: notification
activate W
W--xB:
deactivate W