sw.js

2.85 KB
18/08/2025 12:42
JS
sw.js
const CACHE_NAME = 'blue-mobile-v1';
const ASSETS_TO_CACHE = [
  './',
  './index.html',
  './offline.html',
  './styles.css',
  './app.js',
  './products.json',
  './icons/icon-192.png',
  './icons/icon-512.png',
  'https://cdnjs.cloudflare.com/ajax/libs/bootstrap/5.3.2/css/bootstrap.min.css',
  'https://cdnjs.cloudflare.com/ajax/libs/bootstrap/5.3.2/js/bootstrap.bundle.min.js'
];

self.addEventListener('install', event => {
  event.waitUntil(
    caches.open(CACHE_NAME).then(cache => {
      return cache.addAll(ASSETS_TO_CACHE);
    })
  );
  self.skipWaiting();
});

self.addEventListener('activate', event => {
  event.waitUntil(
    caches.keys().then(keys => Promise.all(
      keys.filter(k => k !== CACHE_NAME).map(k => caches.delete(k))
    ))
  );
  self.clients.claim();
});

self.addEventListener('fetch', event => {
  const url = new URL(event.request.url);

  // Network-first for API (products.json) with cache fallback
  if (url.pathname.endsWith('/products.json')) {
    event.respondWith(
      fetch(event.request).then(resp => {
        const copy = resp.clone();
        caches.open(CACHE_NAME).then(cache => cache.put(event.request, copy));
        return resp;
      }).catch(() => caches.match(event.request))
    );
    return;
  }

  // Navigation requests: try network first, fallback to cached offline page
  if (event.request.mode === 'navigate') {
    event.respondWith(
      fetch(event.request).then(resp => {
        // update cache for navigation
        const copy = resp.clone();
        caches.open(CACHE_NAME).then(cache => cache.put(event.request, copy));
        return resp;
      }).catch(() => caches.match('./offline.html'))
    );
    return;
  }

  // For images, styles, scripts: cache-first (fast)
  if (event.request.destination === 'image') {
    // Try to serve WebP variant when possible
    const url = new URL(event.request.url);
    const webpUrl = url.pathname + '.webp';
    event.respondWith(
      caches.match(webpUrl).then(cachedWebp => {
        if (cachedWebp) return cachedWebp;
        return caches.match(event.request).then(cached => cached || fetch(event.request).then(resp => {
          const copy = resp.clone();
          caches.open(CACHE_NAME).then(cache => cache.put(event.request, copy));
          return resp;
        }));
      })
    );
    return;
  }

  if (event.request.destination === 'style' || event.request.destination === 'script' || event.request.destination === 'font') {
    event.respondWith(
      caches.match(event.request).then(cached => cached || fetch(event.request).then(resp => {
        const copy = resp.clone();
        caches.open(CACHE_NAME).then(cache => cache.put(event.request, copy));
        return resp;
      }))
    );
    return;
  }

  // Default: try cache, then network
  event.respondWith(
    caches.match(event.request).then(cached => cached || fetch(event.request)).catch(() => {})
  );
});