Implementing Offline Resilience in Chrome using Service Worker Interception
Learn how to use Chrome's Service Worker API and Cache Storage to intercept network requests and enable offline functionality for web applications.
13 Dec 2025, 17:31 UTC

The Problem: Network Latency and Offline Failures
Web applications typically fail the moment a user loses connectivity or encounters a "lie-fi" connection (where the device reports a connection, but data isn't moving). To solve this, Chrome utilizes Service Workers—scripts that run in the background, separate from the main browser thread—to act as a programmable proxy. By intercepting network requests, you can serve cached assets instantly, regardless of the network state.
How Service Worker Interception Works
A Service Worker sits between the browser's network stack and the internet. When the browser makes a fetch request, the Service Worker can intercept that request and decide whether to fetch it from the network, serve it from the Cache Storage API (a dedicated browser storage for request/response pairs), or provide a custom fallback response.
Implementation Example: Cache-First Strategy
The following implementation demonstrates a "Cache-First" strategy. This is ideal for static assets like CSS, JS, and images that do not change frequently, as it eliminates network round-trips for repeat visits.
Step 1: Register the worker in your main JavaScript file
if ('serviceWorker' in navigator) {
window.addEventListener('load', () => {
navigator.serviceWorker.register('/sw.js')
.then(reg => console.log('SW registered!', reg))
.catch(err => console.error('SW registration failed:', err));
});
}
Step 2: Create the sw.js worker file
const CACHE_NAME = 'static-assets-v1';
const ASSETS_TO_CACHE = [
'/',
'/styles/main.css',
'/scripts/app.js',
'/images/logo.png'
];
// Install event: Pre-cache essential files
self.addEventListener('install', (event) => {
event.waitUntil(
caches.open(CACHE_NAME).then((cache) => {
return cache.addAll(ASSETS_TO_CACHE);
})
);
});
// Fetch event: Intercept network requests
self.addEventListener('fetch', (event) => {
event.respondWith(
caches.match(event.request).then((cachedResponse) => {
// Return cached version if found, otherwise fetch from network
return cachedResponse || fetch(event.request);
})
);
});
Operational Requirements
- Secure Context: Service Workers only function over HTTPS or
localhost. This prevents "man-in-the-middle" attacks from hijacking network requests. - Scope: The
sw.jsfile's location determines its scope. A worker placed at/js/sw.jscan only intercept requests for URLs starting with/js/. To intercept all site requests, place the worker in the root directory.
Critical Limitations and Common Failures
The Stale Content Trap
Because the "Cache-First" strategy ignores the network if a match is found, users may never see updates to your CSS or JS files even after you deploy a new version. To fix this, you must implement Cache Versioning. By changing static-assets-v1 to static-assets-v2, you trigger a new installation. You must then add an activate event listener to delete the old cache:
self.addEventListener('activate', (event) => {
event.waitUntil(
caches.keys().then((cacheNames) => {
return Promise.all(
cacheNames.filter(name => name !== CACHE_NAME)
.map(name => caches.delete(name))
);
})
);
});
Storage Quotas
Chrome allocates a storage quota based on the user's available disk space. While generous, caching massive video files or high-resolution images can lead to the browser automatically evicting your cache to free up space. Always prioritize critical UI assets over optional media.
Verification and Diagnostics
To verify the implementation in Chrome, use the following steps:
- Open DevTools (F12) > Application tab.
- Select Service Workers in the left sidebar to confirm the worker is "Activated and Running."
- Select Cache Storage to see exactly which files are stored and their response headers.
- Go to the Network tab, check the Offline checkbox, and refresh the page. If the page loads, the interception is successful.
Rollback Procedure
If a Service Worker causes a critical failure (e.g., blocking all network traffic), you can force the browser to stop using it by registering a new worker that immediately unregisters itself:
navigator.serviceWorker.getRegistrations().then(registrations => {
for(let registration of registrations) {
registration.unregister();
}
});0 replies
A thoughtful contribution can make all the difference. Be the first to share one.