How to Build an Offline-First Progressive Web App
A step-by-step guide on how to architect a Progressive Web App with service workers, caching strategies, background sync, and installability for reliable offline experiences.
Register a Service Worker
A Service Worker is a JavaScript file that runs in a background thread separate from the main browser thread. Register it in your main JavaScript file by calling navigator.serviceWorker.register with the path to your service worker file. Check for serviceWorker support in navigator first for backward compatibility. The browser installs the service worker once and it persists across page loads, acting as a programmable proxy between your app and the network.
Implement the Install Event for Precaching
The install event fires once when the service worker first installs. Inside the install event handler, open a named cache using caches.open and call addAll with an array of URLs to precache. This downloads and stores your app shell assets including the HTML, CSS, and JavaScript files needed to render the basic UI. Call event.waitUntil to delay the completion of the install event until all assets are cached successfully.
Implement the Fetch Event to Intercept Network Requests
Every network request made by the page passes through the service worker's fetch event. Inside the handler, inspect the request URL and decide how to respond. You can return a cached response immediately, fetch from the network, or implement a more complex strategy that tries both. Call event.respondWith with a Promise resolving to a Response object to take control of how the request is fulfilled.
Apply the Cache First Strategy for Static Assets
For static assets that rarely change like fonts, images, and versioned JavaScript bundles, use the Cache First strategy. Check the cache first and return the cached response immediately if available. If not in the cache, fetch from the network, store the response in the cache, and return it. This makes the app load instantly from cache on subsequent visits and eliminates network latency for static resources.
Apply the Network First Strategy for API Data
For dynamic API data that changes frequently, use the Network First strategy. Attempt to fetch from the network first. If the network request succeeds, update the cache with the fresh response and return it. If the network request fails due to being offline, fall back to the cached response. This ensures users see the most current data when online while still having stale but functional data when offline.
Implement Background Sync for Offline Actions
When a user performs an action while offline such as submitting a form or sending a message, store the request details in IndexedDB rather than losing it. Register a background sync event using the SyncManager API. When the network connection is restored, the browser fires the sync event in the service worker. Inside the handler, retrieve the queued requests from IndexedDB and replay them against the server automatically.
Create the Web App Manifest for Installability
A Web App Manifest is a JSON file that tells the browser how your app should behave when installed on a device. Define the app name, short name, icons in multiple sizes, start URL, display mode set to standalone to hide the browser UI, theme color, and background color. Link the manifest in your HTML head with a link tag. With the manifest in place and a service worker registered, browsers offer an install prompt allowing users to add the app to their home screen.
Handle Cache Versioning and Cleanup
Each time you deploy new code, update the cache version name in the service worker. In the activate event, compare all existing cache names against the current version and delete any that do not match. Call self.clients.claim inside the activate event to take control of all open tabs immediately without requiring a page reload. Without proper cache cleanup, old cached assets persist indefinitely and users see stale versions of your application.
Ready to master this completely?
Want to upskill yourself, crack your next interview, and get your dream job? Join our comprehensive course to dive deeper with high-quality video tutorials, solve interview questions, and a premium community.

