avtopost.kultmost.ru/static/service-worker.js
2026-09-03 23:03:37 -04:00

202 lines
5.5 KiB
JavaScript

importScripts('https://storage.googleapis.com/workbox-cdn/releases/7.0.0/workbox-sw.js');
workbox.setConfig({ debug: false });
const CACHE_NAME = 'app-cache-v2.1.6';
const MIN_VALID_SIZE = 500;
const ASSETS_TO_CACHE = [
'/pwa2',
'/icon-192x192.png',
'/icon-512x512.png',
'/offline.html',
'/static/Inter-Bold.woff2',
'/static/Inter-SemiBold.woff2',
'/static/Inter-Regular.woff2',
'/static/painter.svg',
'/static/event1.jpg',
'/static/event2.jpg',
'/static/event3.jpg',
'/static/event4.jpg',
'/static/event5.jpg',
'/static/script/share.js',
'/static/script/select.js',
'/static/event6.jpg',
'/static/event7.webp',
'/partner',
];
const NOCACHE_PATHS = [
'/api',
'/form',
];
const VALIDATE_ON_MODIFY_PATHS = [
'/',
'/pwa',
'/paintings',
'/profile',
'/competitions',
'/competition',
'/exhibitions',
'/exhibition',
'/login',
'/registration',
'/artists',
'/my-paints',
'/partner',
'/news',
];
// ——— Lifecycle ———
self.skipWaiting();
workbox.core.clientsClaim();
// Clean old caches + notify clients
self.addEventListener('activate', (event) => {
event.waitUntil(
(async () => {
const keys = await caches.keys();
await Promise.all(
keys
.filter((key) => key !== CACHE_NAME)
.map((key) => {
console.log(`Deleting old cache: ${key}`);
return caches.delete(key);
})
);
const clients = await self.clients.matchAll();
clients.forEach((client) => client.postMessage({ type: 'SW_UPDATED' }));
console.log('Service Worker activated.');
})()
);
});
// ——— Precaching ———
workbox.precaching.precacheAndRoute(
ASSETS_TO_CACHE.map((url) => ({ url, revision: null })),
{
cacheName: CACHE_NAME,
}
);
// ——— Runtime routes ———
// 1. Never cache these paths (NetworkOnly)
workbox.routing.registerRoute(
({ url }) =>
NOCACHE_PATHS.some(
(path) => url.pathname === path || url.pathname.startsWith(path + '/')
),
new workbox.strategies.NetworkOnly()
);
// 2. Paths that should revalidate on Last-Modified / Content-Length
workbox.routing.registerRoute(
({ url }) =>
VALIDATE_ON_MODIFY_PATHS.some(
(path) => url.pathname === path || url.pathname.startsWith(path + '/')
),
new workbox.strategies.NetworkFirst({
cacheName: CACHE_NAME,
plugins: [
new workbox.cacheableResponse.CacheableResponsePlugin({
statuses: [0, 200],
}),
{
// Custom plugin: only update cache when content actually changed
// or when the cached entry is suspiciously small
cacheWillUpdate: async ({ request, response, event }) => {
if (!response || response.status !== 200) return null;
const cache = await caches.open(CACHE_NAME);
const cached = await cache.match(request);
if (!cached) return response;
const contentLength = parseInt(
cached.headers.get('Content-Length') || '0',
10
);
const isTooSmall = contentLength > 0 && contentLength < MIN_VALID_SIZE;
if (isTooSmall) {
console.warn(
`Cached file ${request.url} was too small (${contentLength} bytes). Forcing update.`
);
return response;
}
const [cachedModified, netModified] = await Promise.all([
cached.headers.get('Last-Modified'),
response.headers.get('Last-Modified'),
]);
const [cachedLen, netLen] = await Promise.all([
cached.headers.get('Content-Length'),
response.headers.get('Content-Length'),
]);
if (cachedModified === netModified && cachedLen === netLen) {
console.log(
`Content unchanged for ${new URL(request.url).pathname}, keeping cached version`
);
return null; // do not update cache
}
console.log(`Caching/updating: ${new URL(request.url).pathname}`);
return response;
},
},
],
})
);
// 3. Everything else → CacheFirst (with size safeguard)
workbox.routing.registerRoute(
({ request }) => request.method === 'GET',
new workbox.strategies.CacheFirst({
cacheName: CACHE_NAME,
plugins: [
new workbox.cacheableResponse.CacheableResponsePlugin({
statuses: [0, 200],
}),
{
// Force update when cached response is too small
cachedResponseWillBeUsed: async ({
cacheName,
request,
cachedResponse,
}) => {
if (!cachedResponse) return null;
const contentLength = parseInt(
cachedResponse.headers.get('Content-Length') || '0',
10
);
if (contentLength > 0 && contentLength < MIN_VALID_SIZE) {
console.warn(
`Cached file ${request.url} was too small (${contentLength} bytes). Ignoring cache.`
);
return null; // force network
}
return cachedResponse;
},
},
],
})
);
// ——— Offline fallback for navigation requests ———
workbox.routing.setCatchHandler(async ({ event }) => {
if (event.request.mode === 'navigate') {
const offline = await caches.match('/offline.html');
if (offline) return offline;
const root = await caches.match('/');
if (root) return root;
}
// For non-navigation requests just return whatever we have (or fail)
return Response.error();
});