Lesson 0003 · ~10 minutes
One skill: explain why a new service worker often
waits, when
skipWaiting is worth it, and how two versions coexist
without trash-compacting each other’s caches.
Finish the 4 quiz cards. You should be able to say: “New SW installs beside the old one, waits until no clients, then activates — unless we skipWaiting.”
register → install → activate for the first SWwaitUntil on install = worker discardedYou shipped a fix. User still sees the bug. Three common reasons:
Source of truth: Jake Archibald — lifecycle (Updating section).
Browser re-fetches the same script URL (e.g.
/sw.js) on navigation (and other triggers).
Bytes different → this is a new worker. Same URL on purpose — do not
ship sw-v2.js as your update strategy.
New worker runs install while old is still
active. Precache into a new cache name
(static-v2.
New worker sits in waiting until the old one controls zero clients.
Old gone → activate. Delete obsolete caches here. Then
new navigations use the new SW.
One tab + refresh often keeps the old SW in control during the
navigation. Closing all tabs (or waiting for zero clients)
is what unblocks waiting — unless you
skipWaiting.
| Knob | Does | Use when |
|---|---|---|
skipWaiting()
|
New SW activates as soon as install finishes (skips waiting) | Safe to mix old page + new fetch handler, or user clicked “Update” |
clients.claim()
|
Active SW takes over pages that weren’t controlled yet | First-visit / uncontrolled tabs need SW fetch ASAP |
// common pattern — not free magic; know the risk
self.addEventListener("install", (event) => {
self.skipWaiting();
event.waitUntil(
caches.open("static-v2").then((c) => c.addAll(["/", "/app.js"]))
);
});
Risk of skipWaiting: a page loaded under the old SW suddenly gets later requests from the new SW. Fine for many static apps; dangerous if HTML and API contracts diverge between versions (lifecycle caution).
static-v2, fill it.static-v1 alone while old SW still runs.That is how two versions coexist without one deleting the other’s offline shell mid-session.
Old SW is active. New /sw.js bytes differ and install
succeeds. What is the new worker’s default next state?
User has one tab open. They refresh after deploy. New SW is still “waiting.” Best default explanation?
Product wants the new SW active as soon as install finishes, even with tabs open. Which API?
Old SW still uses cache static-v1. New SW should
precache safely. Best pattern?
skipWaiting trades safety for speed.controllerchange reload patterns — ask in chat (one question
is enough).
Lifecycle → Updating only. You can skip the first-SW half if lesson 2 already stuck.