Skip to content

Commit 3779acc

Browse files
committed
fix(pwa): force sw update; bypass env.js cache
1 parent bd003d2 commit 3779acc

2 files changed

Lines changed: 55 additions & 0 deletions

File tree

app/src/lib/pwa/serviceWorker.ts

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,43 @@ export async function ensureServiceWorkerRegistered(): Promise<ServiceWorkerStat
2626
try {
2727
const scope = `${base || ''}/`;
2828
const registration = await navigator.serviceWorker.register(`${scope}service-worker.js`, { scope });
29+
30+
// Aggressively keep SW updated on static deployments, otherwise users may remain stuck on
31+
// stale bundles/env config for a long time.
32+
try {
33+
await registration.update();
34+
} catch {
35+
// ignore
36+
}
37+
38+
const maybeSkipWaiting = () => {
39+
try {
40+
registration.waiting?.postMessage({ type: 'SKIP_WAITING' });
41+
} catch {
42+
// ignore
43+
}
44+
};
45+
46+
// If a new SW is already waiting, activate it now.
47+
maybeSkipWaiting();
48+
49+
let reloaded = false;
50+
const onControllerChange = () => {
51+
if (reloaded) return;
52+
reloaded = true;
53+
// Hard reload to pick up new bundles and env.
54+
window.location.reload();
55+
};
56+
navigator.serviceWorker.addEventListener('controllerchange', onControllerChange, { once: true });
57+
58+
registration.addEventListener('updatefound', () => {
59+
const worker = registration.installing;
60+
if (!worker) return;
61+
worker.addEventListener('statechange', () => {
62+
if (worker.state === 'installed') maybeSkipWaiting();
63+
});
64+
});
65+
2966
return {
3067
supported,
3168
registered: true,

app/src/service-worker.ts

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,11 +55,29 @@ self.addEventListener('activate', (event) => {
5555
);
5656
});
5757

58+
self.addEventListener('message', (event) => {
59+
if (!event.data || typeof event.data !== 'object') return;
60+
if ((event.data as any).type === 'SKIP_WAITING') {
61+
self.skipWaiting();
62+
}
63+
});
64+
5865
self.addEventListener('fetch', (event) => {
5966
if (event.request.method !== 'GET') return;
6067
const url = new URL(event.request.url);
6168
if (url.origin !== self.location.origin) return;
6269

70+
// Always fetch env from network to avoid stale config (clientId/proxy URL) after deployments.
71+
if (url.pathname.endsWith('/_app/env.js')) {
72+
event.respondWith(
73+
(async () => {
74+
const response = await fetch(event.request, { cache: 'no-store' });
75+
return withIsolationHeaders(response);
76+
})()
77+
);
78+
return;
79+
}
80+
6381
event.respondWith(
6482
(async () => {
6583
const cache = await caches.open(CACHE_NAME);

0 commit comments

Comments
 (0)