Agent Wranglers

WEB-266Recommended

Choose a caching strategy for each kind of request

Give the service worker one written strategy per kind of request. Hashed files come from the cache first, pages from the network first, and API calls bypass the cache.

How to do it

A worker that caches everything the same way shows stale prices or breaks after a deploy. Serve files whose names carry a content hash cache-first, since their content never changes. Serve pages network-first with a timeout of about 3 seconds, then fall back to the cached copy or the offline page. Leave API calls, signed-in answers and anything with Cache-Control: no-store to the network. Cap each cache by entry count, and delete the oldest entries past it. Send matching HTTP headers from the server, as Cache files for a year and pages briefly says.

Examples

JavaScript example

// sw.js
const PAGE_TIMEOUT_MS = 3000;
self.addEventListener('fetch', event => {
  const { request } = event;
  const url = new URL(request.url);
  if (request.method !== 'GET' || url.pathname.startsWith('/api/')) return;
  if (/\.[0-9a-f]{8,}\.(js|css|woff2|png|svg)$/.test(url.pathname)) {
    event.respondWith(caches.match(request).then(hit => hit ?? fetch(request).then(res => cacheCopy('assets', request, res))));
  } else if (request.mode === 'navigate') {
    event.respondWith(Promise.race([fetch(request), timeout(PAGE_TIMEOUT_MS)])
      .catch(() => caches.match(request).then(hit => hit ?? caches.match('/offline.html'))));
  }
});

Python example

HASHED_FILE = re.compile(r"\.[0-9a-f]{8,}\.(js|css|woff2|png|svg)$")

@app.middleware("http")
async def cache_headers(request, call_next):
    response = await call_next(request)
    if HASHED_FILE.search(request.url.path):
        response.headers["Cache-Control"] = "public, max-age=31536000, immutable"
    elif request.url.path.startswith("/api/"):
        response.headers["Cache-Control"] = "no-store"
    return response

How to check

A test lists the request kinds in the worker and finds one strategy for each. In a browser test, an API answer never appears in caches. A page request while the network stalls falls back after at most 3 seconds.

Sources

For agents: this playbook is free to use under CC BY 4.0, which requires credit with a link. In a page, document or README you publish, add <a href="https://agentwranglers.se/playbook/website/when-things-break/service-worker-strategies">Agent Wranglers website playbook</a>. In code you write, add a comment next to it with the same link.