register-service-worker

A tiny script that wires up service worker registration with lifecycle hooks for offline-ready web apps.

Library
npm
v1.7.2
659stars
MIT License

Repository Health

Pre-computed score based on development activity, maintenance, community, maturity, and trend momentum.How we score it →
43/100Fair
Development Activity0
Maintenance20
Community64
Maturity60
Momentum28

Technical Analysis

AI-assessed by reading the actual repository — architecture, code quality, innovation, and documentation.How we score it →
45/100Fair
Architecture55
Code Quality25
Innovation65
Learning Curve35

register-service-worker is a small helper script that handles the boilerplate of registering a service worker in the browser, exposing named lifecycle hooks so an app can react to registration, caching, and update events without writing raw Service Worker API plumbing directly. It began life as the service worker registration snippet bundled with Create React App and was later extracted into its own package, becoming the registration layer used by tools like Vue CLI’s PWA plugin.

Calling register(swUrl, hooks) checks whether the browser supports service workers, distinguishes between localhost development (where it verifies the worker file actually exists and has the right content type before registering) and production, and then emits ready, registered, cached, updatefound, updated, offline, and error callbacks as the underlying ServiceWorkerRegistration progresses through its lifecycle. A companion unregister() function removes any active registration. The whole implementation is a single dependency-free ES module, meant to be consumed through a bundler rather than used standalone in a plain script tag.

What You Get

  • A single register(swUrl, hooks) call that registers a service worker and wires up hooks for every stage of its lifecycle
  • Automatic localhost detection that verifies the service worker file exists (and has a JS content-type) before registering, avoiding confusing dev-mode errors
  • An unregister() helper to tear down an active service worker registration
  • Zero runtime dependencies and a tiny, single-file implementation that ships as an ES module
  • TypeScript type definitions (index.d.ts) for the Hooks object and both exported functions

Common Use Cases

  • Adding offline support to a client-rendered SPA built with webpack, Vite, or another ES-module bundler
  • Showing a “new content is available, please refresh” toast when the updated hook fires after a service worker update installs
  • Powering the service worker registration step baked into scaffolding tools like Vue CLI’s PWA plugin
  • Detecting when a service worker fails to register (404, wrong content-type, offline) during local development

Under The Hood

Architecture The entire package is one small ES module (src/index.js) exporting register and unregister. Control flow is a straightforward branch: on load, register() waits for the window load event, then checks isLocalhost() to pick between checkValidServiceWorker (which fetches the worker file first to validate it exists and is served as JavaScript before registering, specifically to give clearer errors during local development) and registerValidSW (which registers directly in production). Both paths converge on the same emit(hook, ...args) closure that looks up and invokes the matching callback from the hooks object, and both attach .catch(error => handleError(...)) to surface offline versus generic errors separately. There’s no internal state beyond the module-level waitWindowLoad promise, and no abstraction layers beyond this single dispatch function, which keeps the whole thing easy to read in one pass.

Tech Stack The distributable index.js is generated from src/index.js via a tiny build script (scripts/build.js) that runs the source through buble, a lightweight ES2015+-to-ES5 transpiler chosen over Babel for its smaller footprint, with transforms.modules disabled so ES import/export syntax is preserved in the output for bundler consumption. conventional-changelog-cli generates CHANGELOG.md on publish. There are no runtime dependencies at all — the only two devDependencies are buble and conventional-changelog-cli — and the package targets any project with an ES-module-aware bundler (webpack, Vite, Rollup) rather than being usable as a bare <script> include.

Code Quality There are no test files, no CI configuration, and no linter or formatter config anywhere in the repository — quality is enforced entirely by the small surface area and the maintainer’s own review. Error handling is deliberate rather than absent: a dedicated handleError function distinguishes navigator.onLine === false (emits offline) from other failures (emits error), and the localhost validation path explicitly checks both HTTP status and content-type before treating a URL as a real service worker. Naming is plain and descriptive (registerValidSW, checkValidServiceWorker), and comments explain non-obvious browser-compatibility decisions (e.g. why a Promise polyfill fallback exists for waitWindowLoad), but without automated tests correctness rests on manual verification and the project’s long real-world usage history.

API Design The public surface is deliberately minimal: two functions, register(swUrl, hooks) and unregister(), with hooks as a single plain object of named callbacks rather than an event emitter or class instance to manage. This keeps integration to a handful of lines with no setup beyond calling register() once at app startup, and the bundled index.d.ts gives TypeScript users full autocomplete on the hook names and their ServiceWorkerRegistration argument. The tradeoff for that simplicity is a very small README with a single usage example and no dedicated docs site, so nuances like hook ordering or the localhost-specific validation behavior are only discoverable by reading the source.

Join founders buildingwith open source

Opinionated takes, migration guides, cost-saving tips, and insights from the open source ecosystem.

Subscribe on Substack
Join 750+ subscribers

Search