29. HTTP caching and the browser cache
Cache-Control response headers tell the browser (and any intermediate CDN)
how long a response is reusable without asking the server again:
Cache-Control: max-age=31536000, immutable // cache for a year, never revalidate
// (use for hashed filenames: app.a3f21c.js)
Cache-Control: no-cache // always revalidate with the server (via ETag)
// before using the cached copy — NOT "don't cache"
Cache-Control: no-store // never cache at all — for sensitive responses
ETags enable cheap revalidation without re-downloading unchanged
content: the server sends an ETag (a content fingerprint); on the next
request the browser sends If-None-Match: <etag>; if unchanged, the server
replies 304 Not Modified with no body, saving the full download.
// The browser handles this negotiation transparently for you inside fetch() —
// you'll just see it as a 304 in the Network panel with near-zero transfer size.
fetch("/api/data"); // second call with an unchanged resource: 304, body served from disk cache
Beyond the HTTP cache, the Cache API (used by service workers, §40) gives JS explicit, programmatic control over a separate cache storage — the foundation of offline-capable apps.