The Codex / JavaScript / Service Workers & PWA

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

The Codex links only to official documentation and the ECMAScript specification. No third-party tutorials.