v147 · Service Worker · Web APIs
Compatibility Lab
Detects Request.isReloadNavigation on the real Request prototype, shows why page-created requests cannot manufacture a reload navigation, and simulates the service-worker branches for fresh navigations, reloads, history restores, and unsupported browsers.
Note:
isReloadNavigation is only set by the browser for navigation requests delivered to a service worker FetchEvent. Page code can check whether the attribute exists, but new Request(url, { mode: "navigate" }) is rejected by the constructor and cannot fake a real reload.
API probes
Live Request attribute test
Request attribute reflection
Click "Run probe" to inspect Request attributes…
Fallback heuristics comparison
| Detection method | Identifies reload | Notes |
|---|---|---|
| request.isReloadNavigation | ✓ Exact | Chrome 147+. Only in FetchEvent. |
| request.cache === "reload" | ✓ Usually | Shift+Reload only; regular reload may vary. |
| Referrer === current URL | ✗ Fragile | Same-origin navigations share referrer. |
| sessionStorage flag across loads | ~ OK | Works but requires write + read coordination. |
| performance.navigation.type | ✓ Works | Deprecated but widely available as fallback. |
Service worker decision lab
Choose the event a service worker would receive. The native branch uses request.isReloadNavigation when present; the fallback branch shows where older heuristics become ambiguous.
Fallback pattern (service worker)
/* Detect isReloadNavigation support */
const HAS_RELOAD_NAV = 'isReloadNavigation' in Request.prototype;
/* Service worker fetch handler with fallback */
self.addEventListener('fetch', (event) => {
if (event.request.mode !== 'navigate') return;
let isReload;
if (HAS_RELOAD_NAV) {
// Chrome 147+ — exact signal
isReload = event.request.isReloadNavigation;
} else {
// Fallback 1: request.cache header
isReload = event.request.cache === 'reload' || event.request.cache === 'no-cache';
// Fallback 2: performance.navigation (page context only, not reliable in SW)
// Fallback 3: custom header injected by the page before reload
}
if (isReload) {
// User explicitly requested fresh content — go network-first
event.respondWith(
fetch(event.request).catch(() => caches.match(event.request))
);
} else {
// Regular navigation — serve from cache, revalidate in background
event.respondWith(
caches.match(event.request).then(cached =>
cached ?? fetch(event.request).then(resp => {
const clone = resp.clone();
caches.open('nav-cache').then(c => c.put(event.request, clone));
return resp;
})
)
);
}
});