Serve an Offline Page with a Service Worker
Precache a shell and a fallback page, use a network-first strategy for navigation, and clean up old caches so users see a clear offline experience.
Task
Add a service worker that serves a cached fallback when navigation requests fail.
When to use this
When the network drops, the app shows the browser error page instead of a branded offline screen with cached navigation.
Prerequisites
- An HTTPS origin (service workers require a secure context)
- A build step that can emit the offline page
Steps
1. Precache the offline document and shell assets during install.
Expected output: The fallback is available before any runtime fetch.
2. Use a network-first strategy for navigations and fall back to the cached offline page.
Expected output: Online users get fresh HTML; offline users get the fallback.
3. Handle the fetch event only for same-origin GET requests.
Expected output: The worker does not interfere with API POSTs or cross-origin calls.
4. Delete caches whose names no longer match the current version on activate.
Expected output: Storage does not grow with every deploy.
Troubleshooting
Problem
Users stuck on old version
Solution
Use skipWaiting and clients.claim deliberately, or prompt the user to reload, so the new worker takes control.
Problem
Offline page not shown
Solution
Confirm the fallback URL is in the precache list and the navigation fallback is wired into the fetch handler.
Limitations
- Service workers only run in secure contexts and are unsupported in some embedding scenarios.
- Aggressive caching of HTML can serve stale pages if the strategy is cache-first by mistake.
Context
Add a service worker that serves a cached fallback when navigation requests fail. When the network drops, the app shows the browser error page instead of a branded offline screen with cached navigation.
Steps
- Precache the offline document and shell assets during install. Expected: The fallback is available before any runtime fetch.
- Use a network-first strategy for navigations and fall back to the cached offline page. Expected: Online users get fresh HTML; offline users get the fallback.
- Handle the fetch event only for same-origin GET requests. Expected: The worker does not interfere with API POSTs or cross-origin calls.
- Delete caches whose names no longer match the current version on activate. Expected: Storage does not grow with every deploy.
self.addEventListener('fetch', (event) => {
if (event.request.mode === 'navigate') {
event.respondWith(fetch(event.request).catch(() => caches.match('/offline.html')));
}
});
Verify
- The fallback is available before any runtime fetch.
- Online users get fresh HTML; offline users get the fallback.
- The worker does not interfere with API POSTs or cross-origin calls.
- Storage does not grow with every deploy.
Limits
- Service workers only run in secure contexts and are unsupported in some embedding scenarios.
- Aggressive caching of HTML can serve stale pages if the strategy is cache-first by mistake.