Service Workers & PWA
Offline web apps, background sync, push notifications, and the Progressive Web App model.
What it is, in plain English: A Service Worker is a script that runs in the background, separate from your web page, acting as a programmable network proxy. It can intercept every network request your page makes and respond from cache — making your app work offline. Service Workers are the foundation of Progressive Web Apps (PWA): installable web apps that work offline, send push notifications, and feel like native apps.
Making web apps work offline
A Service Worker is a script that sits between your web page and the network. It can catch network requests and serve cached responses — so your app works even when there's no internet connection. It also enables push notifications and background sync.
Browser support note: Service Workers require HTTPS (or localhost for development).
They don't work on
http:// pages in production.
Step 1 — Register the Service Worker
// In your main JavaScript file (app.js or index.js):
if ("serviceWorker" in navigator) {
window.addEventListener("load", async () => {
try {
const reg = await navigator.serviceWorker.register("/sw.js");
console.log("Service Worker registered:", reg.scope);
} catch (error) {
console.error("Registration failed:", error);
}
});
}Step 2 — The Service Worker file (sw.js)
// sw.js — lives at the root of your site
const CACHE = "my-app-v1";
const ASSETS = ["/", "/index.html", "/style.css", "/app.js"];
// install event — cache core files when SW is first installed:
self.addEventListener("install", (event) => {
event.waitUntil(
caches.open(CACHE).then(cache => cache.addAll(ASSETS))
);
self.skipWaiting(); // activate immediately (don't wait for old SW)
});
// activate event — clean up old caches:
self.addEventListener("activate", (event) => {
event.waitUntil(
caches.keys().then(keys =>
Promise.all(
keys.filter(key => key !== CACHE)
.map(key => caches.delete(key))
)
)
);
self.clients.claim(); // take control of open tabs immediately
});
// fetch event — intercept every network request:
self.addEventListener("fetch", (event) => {
event.respondWith(
caches.match(event.request).then(cached => {
if (cached) return cached; // serve from cache
return fetch(event.request); // fall back to network
})
);
});Step 3 — Web App Manifest (for installability)
// manifest.json — makes your app installable ("Add to home screen"):
{
"name": "My App",
"short_name": "App",
"start_url": "/",
"display": "standalone", // hides the browser UI
"background_color": "#ffffff",
"theme_color": "#2563eb",
"icons": [
{ "src": "/icon-192.png", "sizes": "192x192", "type": "image/png" },
{ "src": "/icon-512.png", "sizes": "512x512", "type": "image/png" }
]
}
// Link in index.html:
// <link rel="manifest" href="/manifest.json">
Try It Yourself
Official Sources
- MDN Web Docs — Service Worker API
- MDN Web Docs — Using Service Workers
- web.dev — Progressive Web Apps
- Workbox Documentation
The Codex links only to official documentation and the ECMAScript specification. No third-party tutorials.