PWA Development Guide

Web App Manifest (manifest.json)

{ "name": "My Awesome App", "short_name": "MyApp", "description": "A progressive web app", "start_url": "/", "scope": "/", "display": "standalone", "orientation": "portrait", "theme_color": "#6c63ff", "background_color": "#1c2035", "icons": [ { "src": "/icons/icon-192.png", "sizes": "192x192", "type": "image/png" }, { "src": "/icons/icon-512.png", "sizes": "512x512", "type": "image/png" }, { "src": "/icons/icon-maskable.png", "sizes": "512x512", "type": "image/png", "purpose": "maskable" } ], "categories": ["productivity"], "screenshots": [ { "src": "/screenshots/desktop.png", "sizes": "1280x720", "form_factor": "wide" } ] } <!-- In HTML head --> <link rel="manifest" href="/manifest.json"> <meta name="theme-color" content="#6c63ff">

Service Worker Registration

// main.js if ('serviceWorker' in navigator) { window.addEventListener('load', async () => { try { const reg = await navigator.serviceWorker.register('/sw.js', { scope: '/' }); console.log('SW registered:', reg.scope); } catch (err) { console.error('SW registration failed:', err); } }); }

Caching Strategies

// sw.js — Cache First (for static assets) self.addEventListener('fetch', (event) => { event.respondWith( caches.match(event.request).then(cached => { return cached || fetch(event.request); }) ); }); // Network First (for API calls) self.addEventListener('fetch', (event) => { event.respondWith( fetch(event.request) .then(response => { const clone = response.clone(); caches.open('api-cache').then(cache => cache.put(event.request, clone)); return response; }) .catch(() => caches.match(event.request)) ); }); // Stale While Revalidate (for pages) self.addEventListener('fetch', (event) => { event.respondWith( caches.open('page-cache').then(cache => { return cache.match(event.request).then(cached => { const networkFetch = fetch(event.request).then(response => { cache.put(event.request, response.clone()); return response; }); return cached || networkFetch; }); }) ); });

Caching Strategies Reference

StrategyBest ForFreshness
Cache FirstStatic assets, fonts, imagesStale until updated
Network FirstAPI data, dynamic contentAlways fresh, fallback to cache
Stale While RevalidatePages, content that changes occasionallyFast + fresh on next visit
Cache OnlyPrecached assetsStatic
Network OnlyReal-time data, auth endpointsAlways fresh, no offline