mirror of
https://github.com/Dvorinka/MyClubServer.git
synced 2026-06-04 18:52:56 +00:00
hot fix #1
This commit is contained in:
@@ -1,19 +1,22 @@
|
||||
/* eslint-disable no-restricted-globals */
|
||||
// Service Worker for PWA support and offline functionality
|
||||
|
||||
const CACHE_VERSION = 'v1.0.0';
|
||||
const CACHE_VERSION = 'v1.0.2';
|
||||
const CACHE_NAME = `fotbal-club-cache-${CACHE_VERSION}`;
|
||||
|
||||
// Rate limiting for background updates
|
||||
const BACKGROUND_UPDATE_INTERVAL = 5000; // 5 seconds minimum between updates
|
||||
const lastBackgroundUpdates = new Map();
|
||||
|
||||
// Assets to cache on install
|
||||
const STATIC_ASSETS = [
|
||||
'/',
|
||||
'/index.html',
|
||||
'/static/css/main.css',
|
||||
'/static/js/main.js',
|
||||
'/manifest.json',
|
||||
'/favicon.ico',
|
||||
'/logo192.png',
|
||||
'/logo512.png',
|
||||
'/robots.txt',
|
||||
];
|
||||
|
||||
// API endpoints to cache
|
||||
@@ -75,11 +78,27 @@ self.addEventListener('fetch', (event) => {
|
||||
return;
|
||||
}
|
||||
|
||||
// Only handle same-origin requests
|
||||
if (url.origin !== self.location.origin) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Skip admin routes
|
||||
if (url.pathname.startsWith('/admin')) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Skip background update requests to prevent infinite loops
|
||||
if (request.headers.get('X-SW-Background-Update') === 'true') {
|
||||
return;
|
||||
}
|
||||
|
||||
// Handle SPA navigations with app shell fallback
|
||||
if (request.mode === 'navigate') {
|
||||
event.respondWith(handleNavigationRequest(request));
|
||||
return;
|
||||
}
|
||||
|
||||
// Handle API requests
|
||||
if (url.pathname.startsWith('/api/')) {
|
||||
event.respondWith(handleAPIRequest(request));
|
||||
@@ -96,8 +115,16 @@ async function handleStaticRequest(request) {
|
||||
// Try cache first
|
||||
const cachedResponse = await caches.match(request);
|
||||
if (cachedResponse) {
|
||||
// Return cached response and update in background
|
||||
fetchAndUpdateCache(request);
|
||||
// For static assets with long cache headers, don't update in background
|
||||
const url = new URL(request.url);
|
||||
const isStaticAsset = url.pathname.match(/\.(png|jpg|jpeg|gif|svg|webp|ico|woff|woff2|ttf|eot)$/);
|
||||
const hasLongCache = cachedResponse.headers.get('cache-control')?.includes('max-age=31536000');
|
||||
|
||||
// Only update in background if it's not a static asset with long cache
|
||||
if (!isStaticAsset || !hasLongCache) {
|
||||
fetchAndUpdateCache(request);
|
||||
}
|
||||
|
||||
return cachedResponse;
|
||||
}
|
||||
|
||||
@@ -114,8 +141,8 @@ async function handleStaticRequest(request) {
|
||||
} catch (error) {
|
||||
console.error('[SW] Fetch failed:', error);
|
||||
|
||||
// Return offline page if available
|
||||
const cachedOffline = await caches.match('/offline.html');
|
||||
// Return app shell (index.html) if available
|
||||
const cachedOffline = await caches.match('/index.html');
|
||||
if (cachedOffline) {
|
||||
return cachedOffline;
|
||||
}
|
||||
@@ -129,6 +156,28 @@ async function handleStaticRequest(request) {
|
||||
}
|
||||
}
|
||||
|
||||
// Handle SPA navigation requests - Network First with index.html fallback
|
||||
async function handleNavigationRequest(request) {
|
||||
try {
|
||||
const networkResponse = await fetch(request);
|
||||
if (networkResponse && networkResponse.ok) {
|
||||
return networkResponse;
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('[SW] Navigation fetch failed:', error);
|
||||
}
|
||||
// Fallback to cached index.html (app shell)
|
||||
const cachedIndex = await caches.match('/index.html');
|
||||
if (cachedIndex) {
|
||||
return cachedIndex;
|
||||
}
|
||||
return new Response('Offline - Please check your connection', {
|
||||
status: 503,
|
||||
statusText: 'Service Unavailable',
|
||||
headers: { 'Content-Type': 'text/plain' },
|
||||
});
|
||||
}
|
||||
|
||||
// Handle API requests - Network First strategy with cache fallback
|
||||
async function handleAPIRequest(request) {
|
||||
try {
|
||||
@@ -166,9 +215,28 @@ async function handleAPIRequest(request) {
|
||||
// Update cache in background
|
||||
async function fetchAndUpdateCache(request) {
|
||||
try {
|
||||
const response = await fetch(request);
|
||||
// Skip if this is already a background update request to prevent infinite loops
|
||||
if (request.headers.get('X-SW-Background-Update') === 'true') {
|
||||
return;
|
||||
}
|
||||
|
||||
// Rate limit background updates to prevent excessive requests
|
||||
const now = Date.now();
|
||||
const lastUpdate = lastBackgroundUpdates.get(request.url);
|
||||
if (lastUpdate && (now - lastUpdate) < BACKGROUND_UPDATE_INTERVAL) {
|
||||
return;
|
||||
}
|
||||
lastBackgroundUpdates.set(request.url, now);
|
||||
|
||||
// Use fetch with cache: 'no-store' to bypass service worker and avoid infinite loops
|
||||
const response = await fetch(request.url, {
|
||||
cache: 'no-store',
|
||||
headers: { 'X-SW-Background-Update': 'true' }
|
||||
});
|
||||
|
||||
if (response.ok) {
|
||||
const cache = await caches.open(CACHE_NAME);
|
||||
// Use the original request as key, but the new response
|
||||
cache.put(request, response);
|
||||
}
|
||||
} catch (error) {
|
||||
|
||||
Reference in New Issue
Block a user