Lesson 0002 · ~12 minutes
One skill: explain
register() →
install →
activate →
control
for the first service worker, including scope and why the
registering page often is not controlled yet.
You can sketch a correct first-SW path in a design review: where the
script lives, what scope you get, when to call
register, what waitUntil does on install,
and why “registered” ≠ “this tab is controlled.”
From a secure page (HTTPS or localhost), feature-detect and register the
worker script. The API is
navigator.serviceWorker.register():
if ("serviceWorker" in navigator) {
window.addEventListener("load", () => {
navigator.serviceWorker
.register("/sw.js")
.then((reg) => console.log("scope:", reg.scope))
.catch((err) => console.error(err));
});
}
load so install/precache
bandwidth does not fight first-paint resources on slow mobiles.
First visit cares about time-to-interactive. Delay
register() until after load (or after your framework’s
boot) unless you have a measured reason to register early (e.g.
aggressive runtime caching with clients.claim()).
A service worker only controls
clients
under its
scope. Default scope is ./ relative to the
service worker file URL
(lifecycle article,
Learn PWA):
/sw.js → can cover the whole origin path tree from
/
/app/sw.js → default scope /app/ — pages
under /marketing/ are out of reach
You can pass { scope: "..." }, but you cannot claim a wider
scope than the browser allows for that script location. Practical rule:
put the SW script at the highest path you need to control
(often site root for a whole SPA).
Once register() succeeds at downloading and parsing the
script, the browser runs the
lifecycle. For the
first service worker (no previous version), Jake Archibald’s
model is:
Fetch SW script. Parse/execute failure rejects registration; worker is discarded.
First event, once per SW version. Precache shell here. Extend with
event.waitUntil(promise).
Ready for functional events. Ideal later for deleting old caches when a new version replaces an old one.
Default: the page that called register stays
uncontrolled until refresh/reopen. Consistency
first.
// sw.js
self.addEventListener("install", (event) => {
event.waitUntil(
caches.open("static-v1").then((cache) =>
cache.addAll(["/", "/styles.css", "/app.js"])
)
);
});
self.addEventListener("activate", (event) => {
// first SW: often nothing; updates clean old caches here
});
If the promise passed to waitUntil during
install rejects, installation fails and
that service worker never controls anything. That is intentional: you
can treat precached assets as install-time dependencies
(lifecycle).
This is the #1 first-visit confusion:
navigator.serviceWorker.controller is non-null; page
fetches go through the SW.
Archibald’s dog/cat demo: the first load still hits the network for a
subresource even after activate, because the document itself did not
load under the SW. Refresh, and both document and subresources go
through fetch handlers.
clients.claim() (awareness)
On activate, self.clients.claim() can take
over already-open uncontrolled pages. Useful for early runtime
caching; risky if the SW serves a different world than a plain network
load. Not required boilerplate — know it exists, default to
consistency.
Choose the best answer. Options matched for length. Immediate feedback.
You register /app/sw.js with no scope option. Which
clients can it control by default?
First visit: register('/sw.js') resolves; install and
activate fire. Still, controller is null. Why?
Install handler: waitUntil(cache.addAll([...])) and one
URL 404s so the promise rejects. Result?
Mobile-first SPA, heavy first paint, precache list is large. Best
default for calling register?
register(scriptURL) + secure context + feature detect.
waitUntil: succeed together or discard the SW.
clients.claim() is opt-in, not free magic.
sw.js in a Vite/webpack app — ask in chat.
web.dev — The service worker lifecycle (Jake Archibald)
Read the “first service worker” sections (install, activate, scope,
control, clients.claim). Skip or skim “Updating” until
lesson 3 if short on time. Secondary:
Service worker registration
(when to call register).