WEB-224Optional
Keep working when the network drops
Add a service worker, a small script that sits between the page and the network. Show an offline page and cached pages when the network fails.
How to do it
Precache an offline page. Serve pages network-first, or from cache while refreshing in the background. Serve hashed files cache-first, never cache live or private data, and keep an off switch. Name the cache after the build, and have each page send its build to the worker. On a mismatch, the worker drops its cached pages, so nobody sees an old version after a deploy.
Examples
JavaScript example
// sw.js
const CACHE = 'pages-3f9a1c'; // the build's hash, written in at build time
self.addEventListener('install', e => e.waitUntil(caches.open(CACHE).then(c => c.add('/offline.html'))));
self.addEventListener('activate', e => e.waitUntil(caches.keys().then(keys => Promise.all(keys.filter(k => k !== CACHE).map(k => caches.delete(k))))));
self.addEventListener('fetch', e => {
if (e.request.mode !== 'navigate') return;
e.respondWith(fetch(e.request).then(res => {
// Keep a copy of each page, so a visited page still opens offline
if (res.ok) { const copy = res.clone(); e.waitUntil(caches.open(CACHE).then(c => c.put(e.request, copy))); }
return res;
}).catch(async () => (await caches.match(e.request)) || caches.match('/offline.html')));
});
How to check
In DevTools, go offline. A visited page or the offline page appears.
Measured
On a reference site, a service worker warmed its cache with the page's links after load. In an earlier lab run, the first click went from 216 to 106 ms in Firefox. In WebKit, which did not prefetch, it went from 373 to 180 ms. In Chrome it made no difference beyond prefetch and the HTTP cache.
Sources
Related rules
- APP-52 Say when the network is gone in Web app interface
- APS-19 Clear cached pages and data when someone signs out in Application security
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/offline-and-installed-apps/offline-support">Agent Wranglers website playbook</a>. In code you write, add a comment next to it with the same link.