{
"name": "My App",
"short_name": "MyApp",
"icons": [
{
"src": "/images/icons-vector.svg",
"type": "image/svg+xml",
"sizes": "512x512"
},
{
"src": "/images/icons-192.png",
"type": "image/png",
"sizes": "192x192"
},
{
"src": "/images/icons-512.png",
"type": "image/png",
"sizes": "512x512"
}
],
"id": "/?source=pwa",
"start_url": "/?source=pwa",
"background_color": "#000000",
"display": "standalone",
"scope": "/?source=pwa",
"theme_color": "#000000",
"shortcuts": [],
"description": "My awesome PWA app",
"screenshots": [
{
"src": "/images/screenshot1.png",
"type": "image/png",
"sizes": "540x720",
"form_factor": "narrow"
},
{
"src": "/images/screenshot2.jpg",
"type": "image/jpg",
"sizes": "720x540",
"form_factor": "wide"
}
]
}
const CACHE_NAME = 'V1-CACHE';
const FILES_TO_CACHE = ['/'];
// Install event
self.addEventListener('install', (event) => {
event.waitUntil(
caches.open(CACHE_NAME).then((cache) => cache.addAll(FILES_TO_CACHE))
)
})
// Fetch event
self.addEventListener('fetch', (event) => {
const url = new URL(event.request.url)
// Define route-based strategies
// This is temp as an example of route based strategy
// The user should be able to configure this or we can start
// With sensible defaults
const routes = {
'/api': 'networkFirst',
'.css': 'cacheFirst',
'.js': 'staleWhileRevalidate',
};
let strategy = Object.keys(routes).find((route) => {
if (route.startsWith('.')) {
// Match by file extension
return url.pathname.endsWith(route)
}
// Match by path
return url.pathname.startsWith(route)
});
// Default to the selected option if no match
strategy = routes[strategy] || 'cacheFirst'
// Apply the selected strategy
if (strategy === 'cacheFirst') {
event.respondWith(
caches.match(event.request).then((response) =>
response || fetch(event.request)
)
);
} else if (strategy === 'networkFirst') {
event.respondWith(
fetch(event.request)
.then((response) => {
const clone = response.clone();
caches.open(CACHE_NAME).then((cache) =>
cache.put(event.request, clone)
);
return response;
})
.catch(() => caches.match(event.request))
);
} else if (strategy === 'staleWhileRevalidate') {
event.respondWith(
caches.match(event.request).then((cachedResponse) => {
const fetchPromise = fetch(event.request).then((response) => {
const clone = response.clone();
caches.open(CACHE_NAME).then((cache) =>
cache.put(event.request, clone)
);
return response;
});
return cachedResponse || fetchPromise;
})
);
}
});
// Activate event
self.addEventListener('activate', (event) => {
event.waitUntil(
caches.keys().then((cacheNames) =>
Promise.all(
cacheNames.map((cacheName) => {
if (cacheName !== CACHE_NAME) {
return caches.delete(cacheName)
}
})
)
)
);
});
self.skipWaiting();