fix(sw): point service worker at React shell + bump cache version
The previous SW (pedscribe-v12) precached /js/app.js, /js/auth.js,
and /css/styles.css — all deleted in the previous commit. Without
this fix, every existing PWA install would 404 on the next SW
install attempt and serve stale cached vanilla pages forever.
Changes:
• CACHE_NAME bumped to pedscribe-v13 → activate event evicts the
v12 cache (and any earlier).
• SHELL_ASSETS narrowed to [/, /manifest.json]. Hashed Vite
assets are not precached because their filenames change on
every build — they're served fresh from the network with Vite's
immutable Cache-Control as backup.
• Fetch handler:
- /api/* → bypass SW (medical data must always be fresh).
- /app/assets/* → network-first, cache fallback for offline.
- everything else → cache-first with stale-while-revalidate.
• Promise.allSettled around cache.add() so a single missing
asset can't break the whole SW install.
Existing PWA users get the new shell on their next visit
(skipWaiting + clients.claim).
This commit is contained in:
parent
39d764e1ff
commit
990cbf97ac
1 changed files with 31 additions and 59 deletions
90
public/sw.js
90
public/sw.js
|
|
@ -1,31 +1,29 @@
|
|||
// ============================================================
|
||||
// SERVICE WORKER — Cache shell, network-first for API
|
||||
// Provides offline fallback for app shell while keeping
|
||||
// API calls always fresh (critical for medical data accuracy)
|
||||
// SERVICE WORKER — Cache the React shell + manifest.
|
||||
// Network-first for API (medical data must always be fresh).
|
||||
// Hashed Vite assets are NOT precached — they change every build,
|
||||
// the browser HTTP cache plus immutable Cache-Control handles them.
|
||||
// ============================================================
|
||||
|
||||
var CACHE_NAME = 'pedscribe-v12';
|
||||
var CACHE_NAME = 'pedscribe-v13';
|
||||
var SHELL_ASSETS = [
|
||||
'/',
|
||||
'/index.html',
|
||||
'/css/styles.css',
|
||||
'/js/app.js',
|
||||
'/js/auth.js',
|
||||
'/manifest.json'
|
||||
'/manifest.json',
|
||||
];
|
||||
|
||||
// Install: precache app shell
|
||||
// Install: precache shell. Errors swallowed so a missing single
|
||||
// asset doesn't break SW install entirely.
|
||||
self.addEventListener('install', function(event) {
|
||||
event.waitUntil(
|
||||
caches.open(CACHE_NAME).then(function(cache) {
|
||||
return cache.addAll(SHELL_ASSETS);
|
||||
}).then(function() {
|
||||
return self.skipWaiting();
|
||||
})
|
||||
return Promise.allSettled(SHELL_ASSETS.map(function(url) {
|
||||
return cache.add(url).catch(function() {});
|
||||
}));
|
||||
}).then(function() { return self.skipWaiting(); })
|
||||
);
|
||||
});
|
||||
|
||||
// Activate: clear old caches
|
||||
// Activate: clear old caches (deletes pedscribe-v12 and earlier).
|
||||
self.addEventListener('activate', function(event) {
|
||||
event.waitUntil(
|
||||
caches.keys().then(function(names) {
|
||||
|
|
@ -33,61 +31,35 @@ self.addEventListener('activate', function(event) {
|
|||
names.filter(function(name) { return name !== CACHE_NAME; })
|
||||
.map(function(name) { return caches.delete(name); })
|
||||
);
|
||||
}).then(function() {
|
||||
return self.clients.claim();
|
||||
})
|
||||
}).then(function() { return self.clients.claim(); })
|
||||
);
|
||||
});
|
||||
|
||||
// Fetch: network-first for API, cache-first for static assets
|
||||
self.addEventListener('fetch', function(event) {
|
||||
if (event.request.method !== 'GET') return;
|
||||
var url = new URL(event.request.url);
|
||||
|
||||
// Only handle same-origin requests
|
||||
// Same-origin only; skip cross-origin (CDN, fonts, etc.)
|
||||
if (url.origin !== self.location.origin) return;
|
||||
|
||||
// API calls — always network, never cache (medical data must be fresh)
|
||||
if (url.pathname.startsWith('/api/')) {
|
||||
event.respondWith(fetch(event.request));
|
||||
return;
|
||||
}
|
||||
|
||||
// Component HTML — network-first with cache fallback
|
||||
if (url.pathname.startsWith('/components/')) {
|
||||
// API: network only — never cache medical data.
|
||||
if (url.pathname.startsWith('/api/')) return;
|
||||
// Hashed Vite assets: serve from network, fall back to cache if offline.
|
||||
if (url.pathname.startsWith('/app/assets/')) {
|
||||
event.respondWith(
|
||||
fetch(event.request).then(function(response) {
|
||||
var clone = response.clone();
|
||||
caches.open(CACHE_NAME).then(function(cache) { cache.put(event.request, clone); });
|
||||
return response;
|
||||
}).catch(function() {
|
||||
return caches.match(event.request);
|
||||
})
|
||||
fetch(event.request).catch(function() { return caches.match(event.request); })
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
// Static assets (JS, CSS, icons) — network-first so code updates apply immediately
|
||||
if (url.pathname.match(/\.(js|css|png|ico|woff2?)$/)) {
|
||||
event.respondWith(
|
||||
fetch(event.request).then(function(response) {
|
||||
var clone = response.clone();
|
||||
caches.open(CACHE_NAME).then(function(cache) { cache.put(event.request, clone); });
|
||||
return response;
|
||||
}).catch(function() {
|
||||
return caches.match(event.request);
|
||||
})
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
// HTML pages — network-first
|
||||
// SPA shell + everything else: cache-first with network update.
|
||||
event.respondWith(
|
||||
fetch(event.request).then(function(response) {
|
||||
var clone = response.clone();
|
||||
caches.open(CACHE_NAME).then(function(cache) { cache.put(event.request, clone); });
|
||||
return response;
|
||||
}).catch(function() {
|
||||
return caches.match(event.request) || caches.match('/index.html');
|
||||
caches.match(event.request).then(function(cached) {
|
||||
var fetchPromise = fetch(event.request).then(function(resp) {
|
||||
if (resp && resp.status === 200) {
|
||||
var copy = resp.clone();
|
||||
caches.open(CACHE_NAME).then(function(cache) { cache.put(event.request, copy); });
|
||||
}
|
||||
return resp;
|
||||
}).catch(function() { return cached; });
|
||||
return cached || fetchPromise;
|
||||
})
|
||||
);
|
||||
});
|
||||
|
|
|
|||
Loading…
Reference in a new issue