Skip to content

Registering a Service Worker

Before a service worker can intercept any requests, the page must register it. Registration tells the browser where to find the service worker file and which URLs it should control.

if ('serviceWorker' in navigator) {
navigator.serviceWorker
.register('/sw.js')
.then((registration) => {
console.log('SW registered, scope:', registration.scope);
})
.catch((error) => {
console.error('SW registration failed:', error);
});
}

navigator.serviceWorker.register() returns a Promise that resolves to a ServiceWorkerRegistration object. The most important property on that object is scope.

Always guard the call with 'serviceWorker' in navigator. Browsers that do not support service workers (some very old browsers, or pages served over plain HTTP) will simply skip the block. Never let a missing API crash your page.

The scope determines which pages and sub-paths the service worker controls. By default it is the directory that contains the service worker file:

SW file locationDefault scopePages controlled
/sw.js/The entire origin
/app/sw.js/app/Only /app/ and below
/shop/sw.js/shop/Only /shop/ and below

You can narrow the scope (but never widen it beyond the SW file’s directory) by passing a scope option:

navigator.serviceWorker.register('/sw.js', { scope: '/shop/' });

Service workers only run on secure origins:

  • https:// — any HTTPS page in production.
  • http://localhost and http://127.0.0.1 — explicitly exempted for local development.

Attempting to register on plain http:// (other than localhost) will silently fail or throw a SecurityError. Always deploy your PWA over HTTPS.

The demo below registers a minimal service worker. Open the StackBlitz project and check the browser console — you will see the registration log and the SW’s scope.

Runs a real service worker + manifest in your browser.
What does navigator.serviceWorker.register() return?
On which origins can a service worker be registered?
You place sw.js at /admin/sw.js. What is its default scope?
Why should you wrap the register call with "serviceWorker" in navigator?