From 7dfec466a1be67fe08bc67e6a840a6af2fe1aaa0 Mon Sep 17 00:00:00 2001 From: Myron Blair Date: Sun, 14 Jun 2026 20:23:36 +0000 Subject: [PATCH] Disable service worker and clear all caches SW was caching shop pages and JS files, serving stale versions without the inline onclick handler. Replacing with self-unregistering SW. Co-Authored-By: Claude Sonnet 4.6 --- sw.js | 272 ++-------------------------------------------------------- 1 file changed, 6 insertions(+), 266 deletions(-) diff --git a/sw.js b/sw.js index 6145bc2..f89efcf 100644 --- a/sw.js +++ b/sw.js @@ -1,269 +1,9 @@ -const CACHE_NAME = 'tomsjavajive-v1'; -const STATIC_CACHE = 'tomsjavajive-static-v1'; -const DYNAMIC_CACHE = 'tomsjavajive-dynamic-v1'; - -// Static assets to cache immediately -const STATIC_ASSETS = [ - '/', - '/shop.php', - '/cart.php', - '/assets/css/style.css', - '/assets/js/main.js', - '/assets/images/logo.png', - '/manifest.json', - '/offline.html' -]; - -// Install event - cache static assets -self.addEventListener('install', (event) => { - console.log('[Service Worker] Installing...'); - - event.waitUntil( - caches.open(STATIC_CACHE) - .then((cache) => { - console.log('[Service Worker] Caching static assets'); - return cache.addAll(STATIC_ASSETS.map(url => { - return new Request(url, { cache: 'no-cache' }); - })).catch(err => { - console.log('[Service Worker] Some assets failed to cache:', err); - return Promise.resolve(); - }); - }) - .then(() => self.skipWaiting()) - ); -}); - -// Activate event - clean up old caches +// Unregister this service worker and clear all caches +self.addEventListener('install', () => self.skipWaiting()); self.addEventListener('activate', (event) => { - console.log('[Service Worker] Activating...'); - - event.waitUntil( - caches.keys().then((cacheNames) => { - return Promise.all( - cacheNames - .filter((cacheName) => { - return cacheName !== STATIC_CACHE && - cacheName !== DYNAMIC_CACHE && - cacheName.startsWith('tomsjavajive-'); - }) - .map((cacheName) => { - console.log('[Service Worker] Deleting old cache:', cacheName); - return caches.delete(cacheName); - }) - ); - }) - .then(() => self.clients.claim()) - ); -}); - -// Fetch event - serve from cache or network -self.addEventListener('fetch', (event) => { - const { request } = event; - const url = new URL(request.url); - - // Skip non-GET requests - if (request.method !== 'GET') { - return; - } - - // Skip admin panel - if (url.pathname.startsWith('/admin')) { - return; - } - - // Skip API requests (always network) - if (url.pathname.startsWith('/api')) { - return; - } - - // Handle navigation requests - if (request.mode === 'navigate') { - event.respondWith( - fetch(request) - .then((response) => { - // Clone and cache the response - const responseClone = response.clone(); - caches.open(DYNAMIC_CACHE).then((cache) => { - cache.put(request, responseClone); - }); - return response; - }) - .catch(() => { - // Try to serve from cache - return caches.match(request) - .then((cachedResponse) => { - if (cachedResponse) { - return cachedResponse; - } - // Serve offline page - return caches.match('/offline.html'); - }); - }) + event.waitUntil( + caches.keys() + .then(keys => Promise.all(keys.map(key => caches.delete(key)))) + .then(() => self.registration.unregister()) ); - return; - } - - // Handle static assets (cache-first strategy) - if (isStaticAsset(url.pathname)) { - event.respondWith( - caches.match(request) - .then((cachedResponse) => { - if (cachedResponse) { - // Fetch in background to update cache - fetch(request).then((response) => { - if (response.ok) { - caches.open(STATIC_CACHE).then((cache) => { - cache.put(request, response); - }); - } - }).catch(() => {}); - - return cachedResponse; - } - - return fetch(request).then((response) => { - if (response.ok) { - const responseClone = response.clone(); - caches.open(STATIC_CACHE).then((cache) => { - cache.put(request, responseClone); - }); - } - return response; - }); - }) - ); - return; - } - - // Handle images (cache-first with network fallback) - if (isImageRequest(request)) { - event.respondWith( - caches.match(request) - .then((cachedResponse) => { - if (cachedResponse) { - return cachedResponse; - } - - return fetch(request) - .then((response) => { - if (response.ok) { - const responseClone = response.clone(); - caches.open(DYNAMIC_CACHE).then((cache) => { - cache.put(request, responseClone); - }); - } - return response; - }) - .catch(() => { - // Return placeholder image - return caches.match('/assets/images/placeholder-product.svg'); - }); - }) - ); - return; - } - - // Default: network-first with cache fallback - event.respondWith( - fetch(request) - .then((response) => { - if (response.ok) { - const responseClone = response.clone(); - caches.open(DYNAMIC_CACHE).then((cache) => { - cache.put(request, responseClone); - }); - } - return response; - }) - .catch(() => { - return caches.match(request); - }) - ); }); - -// Helper functions -function isStaticAsset(pathname) { - return pathname.match(/\.(css|js|woff|woff2|ttf|eot)$/i); -} - -function isImageRequest(request) { - return request.destination === 'image' || - request.url.match(/\.(png|jpg|jpeg|gif|svg|webp|ico)$/i); -} - -// Push notification handling -self.addEventListener('push', (event) => { - console.log('[Service Worker] Push received'); - - let data = { title: "Tom's Java Jive", body: 'You have a new notification!' }; - - if (event.data) { - try { - data = event.data.json(); - } catch (e) { - data.body = event.data.text(); - } - } - - const options = { - body: data.body, - icon: '/assets/icons/icon-192.png', - badge: '/assets/icons/badge-72.png', - vibrate: [100, 50, 100], - data: { - url: data.url || '/' - }, - actions: [ - { action: 'view', title: 'View' }, - { action: 'close', title: 'Close' } - ] - }; - - event.waitUntil( - self.registration.showNotification(data.title, options) - ); -}); - -// Notification click handling -self.addEventListener('notificationclick', (event) => { - console.log('[Service Worker] Notification clicked'); - - event.notification.close(); - - if (event.action === 'close') { - return; - } - - const url = event.notification.data?.url || '/'; - - event.waitUntil( - clients.matchAll({ type: 'window', includeUncontrolled: true }) - .then((clientList) => { - // Focus existing window if available - for (const client of clientList) { - if (client.url === url && 'focus' in client) { - return client.focus(); - } - } - // Open new window - if (clients.openWindow) { - return clients.openWindow(url); - } - }) - ); -}); - -// Background sync for cart/orders -self.addEventListener('sync', (event) => { - console.log('[Service Worker] Background sync:', event.tag); - - if (event.tag === 'sync-cart') { - event.waitUntil(syncCart()); - } -}); - -async function syncCart() { - // Get pending cart actions from IndexedDB - // and sync with server - console.log('[Service Worker] Syncing cart...'); -}