Gate A · Job
-
Service worker if the hard problem is origin-scoped
network policy: offline shell, fetch routing, programmable
cache on the request path.
-
Dedicated worker if the hard problem is CPU / pure
data off the UI thread.
-
Cache Storage alone if you only need a warehouse and
no interception.
-
CDN / HTTP cache if static fingerprinted assets and
no offline product requirement.
- Secure context required. Treat SW as progressive enhancement.
Gate B · Lifecycle
-
register(scriptURL) after load on first visit; feature
detect; HTTPS/localhost.
- Scope from SW script path (default
./ relative).
-
First SW: install (precache +
waitUntil) → activate →
control often needs refresh (unless clients.claim).
-
Updates: same URL, byte-diff → install beside old →
waiting until zero clients (refresh trap) → activate.
-
skipWaiting / clients.claim are optional
knobs with mixed-version / first-load risks.
-
Cache names versioned; delete obsolete names on activate.
Gate C · Fetch policy
-
Controlled client →
fetch event;
respondWith owns Response; omit → normal network path.
-
Split navigation vs assets vs API. Clone when return +
put.
-
Strategies (cache-first, network-first, SWR, …): Cache API track /
Offline Cookbook — warehouse vs policy.
Gate D · Ship risks
- Stale shell forever (no versioning/cleanup)
- Update lag / multi-tab waiting
- Versioned SW filename anti-pattern
- Cache-first on live money / checkout
- SW Cache Storage vs HTTP cache fighting
- No DOM / not a CPU offload
-
Debug: Application → SW, Update on reload, skip waiting, shift-reload,
Network “(from ServiceWorker)”
Sentence template
“We use / skip a service worker because
job; lifecycle is
register · scope · install/activate · update plan; fetch policy
is routes + strategies; we own
versioning · waiting · dual-cache · progressive enhancement.”