v147 · Service Worker · demo

Cache Strategy Picker

Explore the two navigation paths a service worker takes based on isReloadNavigation — and see the full service-worker code for each strategy.

Reload → Network First

When the user hits Refresh, they expect fresh content. Bypass the cache entirely and go straight to the network — then update the cache with the new response.

isReloadNavigation
true
strategy
Network First
user intent
"Give me the freshest version"
cache on success
yes — update cache with new response
fallback
cached response if network fails
// sw.js — reload path: network-first
self.addEventListener('fetch', event => {
  if (event.request.mode !== 'navigate') return;
  if (!event.request.isReloadNavigation) return; // only for reloads

  event.respondWith(
    fetch(event.request)
      .then(async networkResponse => {
        const cache = await caches.open('pages-v1');
        cache.put(event.request, networkResponse.clone()); // update cache
        return networkResponse;
      })
      .catch(() => caches.match(event.request)) // offline fallback
  );
});
Navigation → Cache First

Regular link clicks and address-bar navigations benefit from cache-first — sub-100 ms loads with no network round-trip. The cache was already updated by the most recent reload.

isReloadNavigation
false
strategy
Cache First
user intent
"Take me to that page quickly"
cache hit
serve immediately — no network
cache miss
fetch from network, then cache it
// sw.js — navigation path: cache-first
self.addEventListener('fetch', event => {
  if (event.request.mode !== 'navigate') return;
  if (event.request.isReloadNavigation) return; // only for non-reloads

  event.respondWith(
    caches.match(event.request).then(async cached => {
      if (cached) return cached; // instant cache hit
      const networkResponse = await fetch(event.request);
      const cache = await caches.open('pages-v1');
      cache.put(event.request, networkResponse.clone()); // prime cache
      return networkResponse;
    })
  );
});
Combined Service Worker

The complete service worker that handles both navigation types in a single fetch handler. One branch for reload, one for regular navigation — a pattern that was previously impossible to implement cleanly.

// sw.js — full handler using isReloadNavigation
const CACHE = 'pages-v1';

self.addEventListener('fetch', event => {
  if (event.request.mode !== 'navigate') return; // non-navigation fetches handled elsewhere

  if (event.request.isReloadNavigation) {
    // User explicitly asked for fresh content → network first
    event.respondWith(
      fetch(event.request)
        .then(async res => {
          const cache = await caches.open(CACHE);
          cache.put(event.request, res.clone());
          return res;
        })
        .catch(() => caches.match(event.request))
    );
  } else {
    // Regular navigation → cache first for speed
    event.respondWith(
      caches.match(event.request).then(async cached => {
        if (cached) return cached;
        const res = await fetch(event.request);
        const cache = await caches.open(CACHE);
        cache.put(event.request, res.clone());
        return res;
      })
    );
  }
});

Before Chrome 147, this pattern required checking the referrer header or maintaining state in a global variable — neither approach was reliable. isReloadNavigation is the intent-first, specification-blessed signal.

see also