Some checks failed
Deploy MyApp on Same Server / build-and-deploy (push) Failing after 1s
194 lines
5.2 KiB
JavaScript
194 lines
5.2 KiB
JavaScript
const CACHE_NAME = 'greenhome-1766182760520';
|
|
const STATIC_CACHE_NAME = 'greenhome-static-1766182760520';
|
|
|
|
// Static assets to cache on install
|
|
const STATIC_FILES_TO_CACHE = [
|
|
'/',
|
|
'/manifest.json',
|
|
'/icon-192.png',
|
|
'/icon-512.png',
|
|
];
|
|
|
|
// Check if request is for static assets
|
|
function isStaticAsset(url) {
|
|
return (
|
|
url.includes('/_next/static/') ||
|
|
url.includes('/_next/image') ||
|
|
url.match(/\.(js|css|woff|woff2|ttf|eot|svg|png|jpg|jpeg|gif|webp|ico)$/i)
|
|
);
|
|
}
|
|
|
|
// Check if request is for external API (skip caching)
|
|
function isExternalApiRequest(url) {
|
|
return url.startsWith('http') && !url.startsWith(self.location.origin);
|
|
}
|
|
|
|
self.addEventListener('install', (event) => {
|
|
event.waitUntil(
|
|
(async () => {
|
|
const cache = await caches.open(STATIC_CACHE_NAME);
|
|
try {
|
|
await cache.addAll(STATIC_FILES_TO_CACHE);
|
|
} catch (error) {
|
|
console.log('Some static files failed to cache:', error);
|
|
}
|
|
// Don't skip waiting automatically - let user decide when to update
|
|
// await self.skipWaiting();
|
|
})()
|
|
);
|
|
});
|
|
|
|
self.addEventListener('activate', (event) => {
|
|
event.waitUntil(
|
|
(async () => {
|
|
await self.clients.claim();
|
|
|
|
// Remove old caches
|
|
const keys = await caches.keys();
|
|
await Promise.all(
|
|
keys
|
|
.filter((key) => key !== CACHE_NAME && key !== STATIC_CACHE_NAME)
|
|
.map((key) => caches.delete(key))
|
|
);
|
|
})()
|
|
);
|
|
});
|
|
|
|
// Listen for messages from clients (e.g., when user clicks update button)
|
|
self.addEventListener('message', (event) => {
|
|
if (event.data && event.data.type === 'SKIP_WAITING') {
|
|
self.skipWaiting().then(() => {
|
|
// Notify all clients about update
|
|
return self.clients.matchAll();
|
|
}).then((clients) => {
|
|
clients.forEach((client) => {
|
|
client.postMessage({ type: 'SW_UPDATED' });
|
|
});
|
|
});
|
|
}
|
|
});
|
|
|
|
self.addEventListener('fetch', (event) => {
|
|
const { request } = event;
|
|
const url = new URL(request.url);
|
|
|
|
// Skip non-GET requests and external API requests
|
|
if (request.method !== 'GET' || isExternalApiRequest(url.href)) {
|
|
return;
|
|
}
|
|
|
|
// Handle navigation requests (pages)
|
|
if (request.mode === 'navigate') {
|
|
event.respondWith(
|
|
(async () => {
|
|
try {
|
|
// Try network first
|
|
const preloadResponse = await event.preloadResponse;
|
|
if (preloadResponse) {
|
|
const cache = await caches.open(CACHE_NAME);
|
|
cache.put(request, preloadResponse.clone());
|
|
return preloadResponse;
|
|
}
|
|
|
|
const networkResponse = await fetch(request);
|
|
|
|
// Cache successful responses
|
|
if (networkResponse.ok) {
|
|
const cache = await caches.open(CACHE_NAME);
|
|
cache.put(request, networkResponse.clone());
|
|
}
|
|
|
|
return networkResponse;
|
|
} catch (error) {
|
|
// Network failed, try cache
|
|
const cache = await caches.open(CACHE_NAME);
|
|
const cachedResponse = await cache.match(request);
|
|
|
|
if (cachedResponse) {
|
|
return cachedResponse;
|
|
}
|
|
|
|
// Fallback to home page if available
|
|
const homePage = await cache.match('/');
|
|
if (homePage) {
|
|
return homePage;
|
|
}
|
|
|
|
// Last resort: return offline page
|
|
return new Response('Offline - No internet connection', {
|
|
status: 503,
|
|
statusText: 'Service Unavailable',
|
|
headers: { 'Content-Type': 'text/html' },
|
|
});
|
|
}
|
|
})()
|
|
);
|
|
return;
|
|
}
|
|
|
|
// Handle static assets (Cache First strategy)
|
|
if (isStaticAsset(url.href)) {
|
|
event.respondWith(
|
|
(async () => {
|
|
const cache = await caches.open(STATIC_CACHE_NAME);
|
|
const cachedResponse = await cache.match(request);
|
|
|
|
if (cachedResponse) {
|
|
return cachedResponse;
|
|
}
|
|
|
|
try {
|
|
const networkResponse = await fetch(request);
|
|
|
|
// Cache successful responses
|
|
if (networkResponse.ok) {
|
|
cache.put(request, networkResponse.clone());
|
|
}
|
|
|
|
return networkResponse;
|
|
} catch (error) {
|
|
// If network fails and no cache, return error
|
|
return new Response('Resource not available offline', {
|
|
status: 503,
|
|
statusText: 'Service Unavailable',
|
|
});
|
|
}
|
|
})()
|
|
);
|
|
return;
|
|
}
|
|
|
|
// Handle other requests (Network First strategy)
|
|
event.respondWith(
|
|
(async () => {
|
|
const cache = await caches.open(CACHE_NAME);
|
|
|
|
try {
|
|
// Try network first
|
|
const networkResponse = await fetch(request);
|
|
|
|
// Cache successful responses
|
|
if (networkResponse.ok) {
|
|
cache.put(request, networkResponse.clone());
|
|
}
|
|
|
|
return networkResponse;
|
|
} catch (error) {
|
|
// Network failed, try cache
|
|
const cachedResponse = await cache.match(request);
|
|
|
|
if (cachedResponse) {
|
|
return cachedResponse;
|
|
}
|
|
|
|
// Return error if no cache available
|
|
return new Response('Resource not available offline', {
|
|
status: 503,
|
|
statusText: 'Service Unavailable',
|
|
});
|
|
}
|
|
})()
|
|
);
|
|
});
|
|
|