Reference
When to fill the warehouse vs how to answer a fetch. Pair with Lesson 3.
fetch-intercept and respondWith
Cache Storage is the SW’s warehouse — not automatic. Cite: SW caching and HTTP caching.
| Moment | Typical job |
|---|---|
install + waitUntil(addAll) |
Versioned shell / static deps that must succeed or install fails |
activate |
Delete old named caches; keep activation lean |
Runtime on fetch |
Dynamic assets after network (watch bloat) |
| Page / user action | “Save offline” / read-later into a named cache |
| Strategy | Behavior | Classic fits |
|---|---|---|
| Cache only | caches.match only |
Precached versioned static you know is there |
| Network only | fetch only (or no respondWith) |
Analytics, non-GET, must-be-live |
| Cache, falling back to network | match → else network | Offline-first shell / most static |
| Network, falling back to cache | network → catch → match | Prefer fresh; stale ok if offline |
| Stale-while-revalidate | return cache if any; also network → put for next time | Avatars, feeds, “latest next visit” |
| Cache then network (page) | UI shows cache, then updates from network | Timelines / articles (page coordinates both) |
// Cache, falling back to network
event.respondWith(
caches.match(event.request).then((r) => r || fetch(event.request))
);
// Network, falling back to cache
event.respondWith(
fetch(event.request).catch(() => caches.match(event.request))
);
// Stale-while-revalidate (simplified)
event.respondWith(
caches.open("dyn-v1").then(async (cache) => {
const cached = await cache.match(event.request);
const networkPromise = fetch(event.request).then((res) => {
cache.put(event.request, res.clone());
return res;
});
return cached || networkPromise;
})
);
SW “revalidate” may still hit a long-lived HTTP cache unless you plan headers / cache-busting. Prefer longer SW control when you need it; don’t assume the two layers share one TTL story.