pwa.tsannotatedpwa.tssource40 lines · 1.8 KB · raw

@ts-ignore

2import { registerSW } from 'virtual:pwa-register';

jevstrudel: the service worker is in prompt mode (astro.config.mjs). When a new deploy has installed and is waiting, the REPL's update modal (src/jev/UpdateModal.jsx) hears 'jev:update-ready' and calls window.jevUpdate() to switch to it and reload. Checks for a new deploy run on load, every ten minutes, and when the tab comes back into view.

9const CHECK_MS = 10 * 60 * 1000;

Switch to the waiting deploy and reload into it. This messages the waiting worker itself rather than calling registerSW's updateSW: that reloads only on a Workbox 'controlling' event marked as an update, and Workbox marks a deploy found by the periodic check below as external, so the worker activated and the page never reloaded (measured 2026-09-24).

16async function switchToWaiting() {
17  const registration = await navigator.serviceWorker.getRegistration();
18  const waiting = registration?.waiting;
19  if (!waiting) return location.reload();
20  navigator.serviceWorker.addEventListener('controllerchange', () => location.reload(), { once: true });
21  waiting.postMessage({ type: 'SKIP_WAITING' });
22  setTimeout(() => location.reload(), 5000); // in case controllerchange never comes
23}
25registerSW({
26  immediate: true,
27  onNeedRefresh() {
28    (window as any).jevUpdate = switchToWaiting;
29    (window as any).jevUpdateReady = true;
30    window.dispatchEvent(new Event('jev:update-ready'));
31  },
32  onRegisteredSW(_url: string, registration?: ServiceWorkerRegistration) {
33    if (!registration) return;
34    const check = () => registration.update().catch(() => {});
35    setInterval(check, CHECK_MS);
36    document.addEventListener('visibilitychange', () => {
37      if (document.visibilityState === 'visible') check();
38    });
39  },
40});