Skip to content
Home
Progressive Web Apps: Offline and Push Notification Guide

Progressive Web Apps: Offline and Push Notification Guide

Web Development Web Development 8 min read 1559 words Beginner ExcellentWiki Editorial Team

Progressive Web Apps combine the reach of the web with the capabilities of native applications. PWAs work offline, send push notifications, install on user devices, and provide fast, reliable experiences regardless of network quality. Google, Microsoft, and Samsung have invested heavily in PWA technologies, with PWAs now distributable through Google Play, the Microsoft Store, and Samsung Galaxy Store. Major companies including Twitter, Pinterest, Spotify, and Uber have adopted PWAs to improve mobile engagement — Pinterest’s PWA drove a 60% increase in core engagement and 44% increase in user-generated ad revenue.

Core PWA Requirements

Three technical requirements define a PWA: a web app manifest, a service worker, and HTTPS. The web app manifest provides metadata — name, icons, theme colors, and display mode. The service worker enables offline functionality, caching, and push notifications. HTTPS ensures secure communication between the app and server. Without any of these three, browsers will not treat your application as installable.

The manifest file is a JSON document linked in your HTML’s <head>. The display property controls the browser chrome — standalone removes browser UI for a native app feel, fullscreen takes the entire screen for immersive experiences, minimal-ui shows minimal navigation controls. The start_url defines the entry point when a user opens the installed app. scope restricts which URLs the PWA can navigate to — pages outside scope open in a regular browser tab.

Service workers are JavaScript files that run in a separate thread, independent of the web page. They cannot access the DOM, window, or document objects. Their power comes from intercepting network requests, managing caches, and handling push events. Service workers persist between page loads, enabling offline functionality that survives browser restarts. The service worker lifecycle — install, activate, fetch — determines when and how the worker controls pages.

Service Worker Lifecycle and Events

Service workers go through a defined lifecycle: install, activate, and fetch. The install event fires when the browser downloads and registers the service worker file. This event is where you cache static assets — HTML, CSS, JavaScript, fonts, and images that make up the application shell. The waitUntil() method extends the install event until the caching completes, preventing the service worker from activating until all critical resources are cached.

The activate event fires after installation completes and the old service worker is no longer controlling pages. This event is where you clean up old caches from previous versions. The clients.claim() method immediately takes control of all open pages without waiting for navigation. Cache versioning in the cache name — my-app-v1, my-app-v2 — enables clean upgrades where the activate handler deletes outdated caches.

The fetch event intercepts every network request from controlled pages. The event handler can serve from cache, fetch from network, or combine both strategies. The respondWith() method provides the response to the intercepted request. Service workers can modify responses (add headers, transform HTML), serve fallback content when the network is unavailable, or construct synthetic responses entirely in code.

Cache Strategies for Different Content Types

Cache-first strategy serves content from cache and only fetches from network when the cache misses. This strategy provides instant loading for repeat visits — the response comes from the local cache without network latency. Use it for static assets: application shell files, framework libraries (React, Vue), logo images, and icon files. The downside is that users see stale content until the next service worker update installs and activates.

Network-first strategy tries the network first and falls back to cache on failure. Use it for API responses, dynamic content, and frequently updated data. If the network succeeds, update the cache for subsequent offline access. If it fails, serve the cached version. This strategy balances freshness with reliability — users see current data when online and recently cached data when offline.

Stale-while-revalidate serves the cached version immediately while fetching a fresh version in the background. The cache is updated with fresh data for subsequent requests. Use this for non-critical resources — user avatars, analytics scripts, and secondary content that doesn’t require real-time accuracy. Users always see something instantly, and the content updates seamlessly on subsequent visits.

Cache-only serves assets that must work offline unconditionally — the application shell, offline fallback page, and critical CSS. Network-only handles sensitive operations — payment processing, form submissions, and authentication — that require server validation and must never be served stale.

Push Notifications Architecture

Push notifications require three components: a push service (managed by the browser vendor), a service worker to handle push events, and user permission. The Web Push API uses public/private key cryptography (VAPID) — the application server sends encrypted messages through the push service, which delivers them to the user’s browser even when the website isn’t open.

Subscribing a user requires registration.pushManager.subscribe() with a VAPID public key. The subscription object includes the endpoint URL and encryption keys, which must be sent to your server for storage. When sending a notification, the server encrypts the payload with the user’s public key and sends it to the endpoint URL. The push service delivers the message to the appropriate browser.

The service worker’s push event handler receives the payload and displays it with registration.showNotification(title, options). Options include notification body text, icon, badge (for Android status bar), vibration pattern, and action buttons for quick responses. The notificationclick event handles user interaction — opening a specific URL, focusing an existing window, or performing an action.

Web App Manifest Configuration

The manifest file supports extensive configuration for installation and display. The icons array specifies app icons at multiple sizes — 192x192 for the splash screen (generated automatically by browsers), 512x512 for the Play Store listing. The screenshots array provides promotional images for app stores. categories classifies the app in app directories.

The related_applications field links to native app versions on app stores, enabling the “Install native app” prompt instead of the PWA. The prefer_related_applications flag tells Chrome to recommend the native app over the PWA. The iarc_rating_id provides content rating for app store compliance.

Installation and Update Flow

The browser triggers a beforeinstallprompt event when it determines the PWA is installable — the manifest is valid, the service worker is registered with a fetch handler, and the user has interacted with the site (clicked, scrolled, or typed). Suppress the automatic prompt with event.preventDefault() and show your own install button with clear messaging like “Install App” or “Add to Home Screen.”

The install prompt is a one-shot operation — once the user accepts or dismisses, it cannot be triggered again without additional user interaction. Test installation flows across browsers — Chrome, Edge, Firefox, and Safari each have different installation behaviors. Safari on iOS lacks the beforeinstallprompt event but allows manual “Add to Home Screen” through the share menu.

Service worker updates check for byte-differences in the worker file on every navigation event. When a new version is detected, it installs in the background but doesn’t activate until all pages controlled by the old worker close. The skipWaiting() method activates the new worker immediately, and clients.claim() takes control of open pages without requiring page reload.

Service Worker Lifecycle

The service worker lifecycle has three phases: installation, activation, and fetch handling. The install event caches static assets. The activate event cleans up old caches. The fetch event intercepts network requests and serves cached responses. Service workers only control pages loaded after they are activated — use clients.claim() to take control immediately. The self.skipWaiting() call in the install step activates a new service worker as soon as it finishes installing, overriding the default wait-for-existing-pages behavior.

Offline Strategies

Choose caching strategies based on resource type. Cache-first: serve from cache, fetch as fallback — for static assets. Network-first: fetch from network, fall back to cache — for API responses. Stale-while-revalidate: serve from cache, fetch in background to update cache — for content that changes but tolerates slight staleness. Cache-only: never fetch — for offline-critical resources. The Workbox library provides declarative strategies and runtime caching for common patterns.

FAQ

What is the difference between a PWA and a native app? PWAs run in the browser and don’t require app store installation. They provide many native features — offline support, push notifications, home screen installation — but have limited access to device hardware (NFC, Bluetooth, USB). PWAs update automatically without app store approval.

Do PWAs work on iOS? Safari supports service workers and manifests since iOS 16.4. Push notifications for PWAs arrived in iOS 16.4. Some features are limited — no background sync, limited cache size, no beforeinstallprompt event. PWAs work but the experience is more limited than Android.

How do I test service workers locally? Chrome DevTools’ Application panel provides service worker debugging, cache inspection, and push notification simulation. Use localhost or HTTPS — service workers require secure contexts. Incognito mode helps test fresh installations without cached data conflicts.

What is the cache size limit for PWAs? Cache limits vary by browser. Chrome allows approximately 50% of available disk space per origin. Firefox limits to roughly 10% of disk space. Safari caps at approximately 50 MB. Monitor cache usage and implement cleanup strategies for applications exceeding typical limits.

Can PWAs access device hardware? Limited access compared to native apps. PWAs can access geolocation, camera (through getUserMedia), microphone, accelerometer, and gyroscope. They cannot access NFC, Bluetooth (Web Bluetooth is limited), USB, or the filesystem directly.

For more performance techniques, see our web performance optimization guide and web performance monitoring guide.

Section: Web Development 1559 words 8 min read Beginner 756 articles in section Report inaccuracy Back to top