Progressive Web Apps: The Future of Mobile-First Development
Progressive Web Apps (PWAs) combine the best of web and mobile apps. They're fast, reliable, work offline, and can be installed on users' devices—all without app store approval.
What Makes a PWA?
Three core requirements:
- HTTPS: Secure connection required
- Service Worker: Enables offline functionality
- Web App Manifest: Defines app metadata
Benefits of PWAs
For Users:
- No app store downloads
- Smaller file sizes
- Works offline
- Fast loading
- Push notifications
For Developers:
- Single codebase for all platforms
- Easier updates (no approval process)
- Lower development costs
- Better SEO than native apps
For Business:
- Higher conversion rates
- Improved engagement
- Reduced bounce rates
- Lower acquisition costs
Implementing a Service Worker
// service-worker.js
const CACHE_NAME = 'my-pwa-v1'
const urlsToCache = [
'/',
'/styles/main.css',
'/scripts/main.js',
'/images/logo.png'
]
// Install event - cache assets
self.addEventListener('install', (event) => {
event.waitUntil(
caches.open(CACHE_NAME)
.then((cache) => cache.addAll(urlsToCache))
)
})
// Fetch event - serve from cache, fallback to network
self.addEventListener('fetch', (event) => {
event.respondWith(
caches.match(event.request)
.then((response) => response || fetch(event.request))
)
})
// Activate event - clean old caches
self.addEventListener('activate', (event) => {
event.waitUntil(
caches.keys().then((cacheNames) => {
return Promise.all(
cacheNames
.filter((name) => name !== CACHE_NAME)
.map((name) => caches.delete(name))
)
})
)
})
Web App Manifest
{
"name": "My Progressive Web App",
"short_name": "MyPWA",
"description": "A progressive web application",
"start_url": "/",
"display": "standalone",
"background_color": "#ffffff",
"theme_color": "#3b82f6",
"orientation": "portrait",
"icons": [
{
"src": "/icons/icon-192.png",
"sizes": "192x192",
"type": "image/png"
},
{
"src": "/icons/icon-512.png",
"sizes": "512x512",
"type": "image/png"
}
]
}
Offline Functionality
Cache Strategies
Cache First: For static assets
// Serve from cache, update cache in background
caches.match(request).then(cached => {
const fetched = fetch(request).then(response => {
cache.put(request, response.clone())
return response
})
return cached || fetched
})
Network First: For dynamic content
// Try network first, fallback to cache
fetch(request)
.catch(() => caches.match(request))
Push Notifications
// Request permission
Notification.requestPermission().then(permission => {
if (permission === 'granted') {
return registration.pushManager.subscribe({
userVisibleOnly: true,
applicationServerKey: publicVapidKey
})
}
})
// Handle push event in service worker
self.addEventListener('push', (event) => {
const data = event.data.json()
event.waitUntil(
self.registration.showNotification(data.title, {
body: data.body,
icon: '/icons/icon-192.png',
badge: '/icons/badge.png'
})
)
})
App Shell Architecture
Load UI shell instantly, then fetch content:
// App shell - cached for instant load
export default function AppShell({ children }: Props) {
return (
<html>
<head>
<link rel="manifest" href="/manifest.json" />
</head>
<body>
<Header />
<main>{children}</main>
<Navigation />
</body>
</html>
)
}
Install Prompt
let deferredPrompt: any
window.addEventListener('beforeinstallprompt', (e) => {
e.preventDefault()
deferredPrompt = e
showInstallButton()
})
function handleInstallClick() {
deferredPrompt.prompt()
deferredPrompt.userChoice.then((choice: any) => {
if (choice.outcome === 'accepted') {
console.log('User accepted the install prompt')
}
deferredPrompt = null
})
}
Performance Optimization
Lighthouse Score Goals:
- Performance: 90+
- Accessibility: 90+
- Best Practices: 90+
- SEO: 90+
- PWA: 100
Techniques:
- Code splitting
- Lazy loading
- Image optimization
- Minification
- Compression (gzip/brotli)
Testing Your PWA
Tools:
- Lighthouse (Chrome DevTools)
- PWA Builder
- Workbox (Google)
Checklist: ✅ Loads instantly ✅ Works offline ✅ Can be installed ✅ Sends push notifications ✅ Secure (HTTPS) ✅ Responsive design ✅ Fast on 3G networks
Popular PWA Examples
- Twitter Lite
- Starbucks
- Uber
- Spotify
Next.js PWA
npm install next-pwa
// next.config.js
const withPWA = require('next-pwa')({
dest: 'public',
register: true,
skipWaiting: true
})
module.exports = withPWA({
// your Next.js config
})
Ready to build a PWA? Contact us for expert development services.
Tags
LetsGrow Dev Team
Marketing Technology Experts
