UNPKG

gentelella

Version:

Gentelella v4 — free admin template. 60 pages, 20 chart variants, fully interactive inbox & kanban, live theme generator, component playground, PWA-ready. Vite 8, vanilla JS, no Bootstrap, no jQuery.

66 lines (57 loc) 2.44 kB
// Gentelella v4 — service worker // Strategy: cache-first for hashed assets (Vite emits content-hashed URLs), // network-first for HTML so navigations always pull the freshest shell, with // a fallback to the offline page when the network is unavailable. // Bump the suffix on every release to bust users' caches when CSS/JS hashes // change but the same URL is requested. Activate handler clears old caches. const CACHE = 'gentelella-v4-r2'; // Subpath-aware: scope is the directory the SW is registered against. Under // `/` it's `https://example.com/`; under `/theme/gentelella-v4-rc1/` it's that // path. Resolving relative URLs against the scope makes the SW work in both. const SCOPE = self.registration?.scope || self.location.origin + '/'; const OFFLINE_URL = new URL('production/offline.html', SCOPE).href; const PRECACHE = [OFFLINE_URL]; self.addEventListener('install', (event) => { event.waitUntil( caches.open(CACHE) .then((c) => c.addAll(PRECACHE).catch(() => {})) .then(() => self.skipWaiting()) ); }); self.addEventListener('activate', (event) => { event.waitUntil( caches.keys() .then((keys) => Promise.all(keys.filter((k) => k !== CACHE).map((k) => caches.delete(k)))) .then(() => self.clients.claim()) ); }); self.addEventListener('fetch', (event) => { const req = event.request; if (req.method !== 'GET') return; const url = new URL(req.url); // Only handle same-origin requests; pass through cross-origin (Google Fonts, CDNs, etc.). if (url.origin !== self.location.origin) return; // HTML — network first, fallback to cache, then offline page. if (req.mode === 'navigate' || req.headers.get('accept')?.includes('text/html')) { event.respondWith( fetch(req) .then((res) => { const copy = res.clone(); caches.open(CACHE).then((c) => c.put(req, copy)).catch(() => {}); return res; }) .catch(async () => (await caches.match(req)) || (await caches.match(OFFLINE_URL)) || Response.error()) ); return; } // Hashed assets (/js, /assets, /images, /fonts) — cache-first. if (/\/(js|assets|images|fonts)\//.test(url.pathname)) { event.respondWith( caches.match(req).then((hit) => hit || fetch(req).then((res) => { const copy = res.clone(); caches.open(CACHE).then((c) => c.put(req, copy)).catch(() => {}); return res; })) ); } });