What are Progressive Web Apps (PWAs) and how do you implement them?

🎨 Frontend Web Development• 9/21/2025
Understanding PWA concepts, service workers, offline functionality, and implementing app-like experiences on the web.

Progressive Web Apps (PWAs)

What are PWAs?

PWAs are web applications that use modern web capabilities to deliver app-like experiences to users. They're reliable, fast, and engaging.

Core Features

1. Reliable

  • Load instantly, even on uncertain network conditions
  • Work offline or with poor connectivity
  • Service workers enable offline functionality

2. Fast

  • Smooth interactions and animations
  • Quick loading and response times
  • Efficient caching strategies

3. Engaging

  • Home screen installation
  • Push notifications
  • Full-screen experience
  • App-like navigation

Key Technologies

1. Service Workers

// Register service worker
if ('serviceWorker' in navigator) {
    navigator.serviceWorker.register('/service-worker.js')
        .then(registration => console.log('SW registered'))
        .catch(error => console.log('SW registration failed'));
}

// service-worker.js
self.addEventListener('install', event => {
    event.waitUntil(
        caches.open('v1').then(cache => {
            return cache.addAll([
                '/',
                '/styles.css',
                '/app.js',
                '/offline.html'
            ]);
        })
    );
});

self.addEventListener('fetch', event => {
    event.respondWith(
        caches.match(event.request).then(response => {
            return response || fetch(event.request);
        })
    );
});

2. Web App Manifest

{
  "name": "My PWA",
  "short_name": "PWA",
  "start_url": "/",
  "display": "standalone",
  "background_color": "#ffffff",
  "theme_color": "#000000",
  "icons": [
    {
      "src": "icon-192.png",
      "sizes": "192x192",
      "type": "image/png"
    },
    {
      "src": "icon-512.png",
      "sizes": "512x512",
      "type": "image/png"
    }
  ]
}

Caching Strategies

1. Cache First

// Good for: App shell, static assets
self.addEventListener('fetch', event => {
    event.respondWith(
        caches.match(event.request).then(response => {
            return response || fetch(event.request);
        })
    );
});

2. Network First

// Good for: Dynamic content, API calls
self.addEventListener('fetch', event => {
    event.respondWith(
        fetch(event.request).catch(() => {
            return caches.match(event.request);
        })
    );
});

3. Stale While Revalidate

// Good for: Frequently updated content
self.addEventListener('fetch', event => {
    event.respondWith(
        caches.open('dynamic').then(cache => {
            return cache.match(event.request).then(response => {
                const fetchPromise = fetch(event.request).then(networkResponse => {
                    cache.put(event.request, networkResponse.clone());
                    return networkResponse;
                });
                return response || fetchPromise;
            });
        })
    );
});

Push Notifications

Client-side Subscription

function subscribeUser() {
    navigator.serviceWorker.ready.then(registration => {
        return registration.pushManager.subscribe({
            userVisibleOnly: true,
            applicationServerKey: urlBase64ToUint8Array(vapidPublicKey)
        });
    }).then(subscription => {
        // Send subscription to server
        sendSubscriptionToServer(subscription);
    });
}

Service Worker Push Handler

self.addEventListener('push', event => {
    const options = {
        body: event.data ? event.data.text() : 'Default message',
        icon: '/icon-192.png',
        badge: '/badge-72.png',
        vibrate: [100, 50, 100],
        data: {
            dateOfArrival: Date.now(),
            primaryKey: '2'
        },
        actions: [
            {
                action: 'explore',
                title: 'Explore',
                icon: '/explore.png'
            },
            {
                action: 'close',
                title: 'Close',
                icon: '/close.png'
            }
        ]
    };
    
    event.waitUntil(
        self.registration.showNotification('PWA Notification', options)
    );
});

Installation and Updates

Installation Prompt

let deferredPrompt;

window.addEventListener('beforeinstallprompt', event => {
    event.preventDefault();
    deferredPrompt = event;
    showInstallButton();
});

function showInstallPrompt() {
    if (deferredPrompt) {
        deferredPrompt.prompt();
        deferredPrompt.userChoice.then(result => {
            if (result.outcome === 'accepted') {
                console.log('User accepted the install prompt');
            }
            deferredPrompt = null;
        });
    }
}

Update Handling

self.addEventListener('message', event => {
    if (event.data && event.data.type === 'SKIP_WAITING') {
        self.skipWaiting();
    }
});

// In main app
navigator.serviceWorker.addEventListener('controllerchange', () => {
    window.location.reload();
});

Testing PWAs

Lighthouse Audit

  • Performance metrics
  • PWA compliance check
  • Best practices validation
  • Accessibility testing

Tools and Frameworks

  • Workbox: Google's PWA library
  • PWA Builder: Microsoft's PWA tools
  • Offline.js: Offline detection
  • sw-precache: Service worker generation

Benefits

  1. App-like Experience: Native app feel
  2. Offline Functionality: Works without internet
  3. Push Notifications: Re-engage users
  4. Home Screen Installation: Easy access
  5. Responsive Design: Works on all devices
  6. Secure: HTTPS requirement
  7. Cost Effective: One codebase for all platforms
By: System Admin