Quick Answer: What is an Offline-First PWA?#
The 3 Architectural Pillars of Offline-First PWAs#
At Rajput Bhavin Engineering, we architect PWAs across three core technical layers:
┌─────────────────────────────────────────────────────────────┐
│ PWA Offline-First Architecture │
├─────────────────────┬───────────────────────────────────────┤
│ Web App Manifest │ Installation metadata & standalone UI │
│ Service Worker │ Network proxy & caching strategies │
│ IndexedDB Storage │ Local structured relational data sync │
└─────────────────────┴───────────────────────────────────────┘
1. Service Worker Caching Strategies Compared#
A Service Worker intercepts every HTTP fetch request made by the browser. Selecting the correct caching strategy per resource type is critical:
2. Production Service Worker Implementation (public/sw.js)#
const CACHE_NAME = 'rbe-pwa-v1';
const STATIC_ASSETS = [
'/',
'/manifest.json',
'/favicon.ico',
'/offline.html',
];
// 1. Install Event: Pre-cache core application shell
self.addEventListener('install', (event) => {
event.waitUntil(
caches.open(CACHE_NAME).then((cache) => {
return cache.addAll(STATIC_ASSETS);
})
);
self.skipWaiting();
});
// 2. Activate Event: Clean up old versioned caches
self.addEventListener('activate', (event) => {
event.waitUntil(
caches.keys().then((keys) => {
return Promise.all(
keys.filter((key) => key !== CACHE_NAME).map((key) => caches.delete(key))
);
})
);
self.clients.claim();
});
// 3. Fetch Event: Stale-While-Revalidate with Offline Fallback
self.addEventListener('fetch', (event) => {
if (event.request.method !== 'GET') return;
event.respondWith(
caches.open(CACHE_NAME).then(async (cache) => {
const cachedResponse = await cache.match(event.request);
const networkFetch = fetch(event.request)
.then((response) => {
if (response.status === 200) {
cache.put(event.request, response.clone());
}
return response;
})
.catch(async () => {
// If network fails and no cache exists, return custom offline page
return cachedResponse || (await cache.match('/offline.html'));
});
return cachedResponse || networkFetch;
})
);
});
3. Bi-Directional Offline Sync with IndexedDB & Background Sync#
When a field worker, delivery driver, or warehouse manager performs an action offline (such as creating an invoice or updating stock), we persist the mutation in local IndexedDB:
import { openDB } from 'idb';
const dbPromise = openDB('offline-mutations-db', 1, {
upgrade(db) {
db.createObjectStore('pending-mutations', { keyPath: 'id', autoIncrement: true });
},
});
export async function queueOfflineAction(endpoint: string, payload: any) {
const db = await dbPromise;
await db.add('pending-mutations', {
endpoint,
payload,
timestamp: Date.now(),
});
// Register Background Sync if supported
if ('serviceWorker' in navigator && 'SyncManager' in window) {
const registration = await navigator.serviceWorker.ready;
await (registration as any).sync.register('sync-pending-mutations');
}
}
When the device regains cellular 5G/Wi-Fi connection, the Service Worker background event triggers, replaying queued mutations to the server idempotently.
4. Web App Manifest (public/manifest.json)#
{
"name": "Rajput Bhavin Engineering",
"short_name": "RBE Portal",
"description": "High-Performance Software & AI Systems in Ahmedabad",
"start_url": "/",
"display": "standalone",
"background_color": "#050505",
"theme_color": "#3b82f6",
"icons": [
{
"src": "/icons/icon-192x192.png",
"sizes": "192x192",
"type": "image/png",
"purpose": "any maskable"
},
{
"src": "/icons/icon-512x512.png",
"sizes": "512x512",
"type": "image/png",
"purpose": "any maskable"
}
]
}
Build Offline-Resilient Web Platforms with Rajput Bhavin#
Ensure your web applications operate seamlessly under spotty mobile connectivity and harsh industrial warehouse environments.
- ✦Explore our Mobile App Development Services
- ✦Discover our Custom ERP Software Development
- ✦Schedule a Technical Discovery Session with Rajput Bhavin today.