Abandoned this as being over the top, but saving it as this Gist.
import { isDev } from '@builder.io/qwik/build';
let memo: Promise<ServiceWorker> | null;
export async function getActiveServiceWorker(): Promise<ServiceWorker> {
if (memo) {
const serviceWorker = await memo;
if (serviceWorker.state === 'activated') return serviceWorker;
}
memo = registerServiceWorker();
return await memo;
}
async function registerServiceWorker(): Promise<ServiceWorker> {
if ('serviceWorker' in navigator) {
await onWindowLoaded();
const registration = await registerServiceWorker();
const serviceWorker = await onActiveServiceWorker(registration);
return serviceWorker;
function registerServiceWorker() {
return navigator.serviceWorker.register(!isDev ? '/service-worker.js' : '/dev-sw.js?dev-sw', {
type: !isDev ? 'classic' : 'module',
});
}
function onWindowLoaded() {
return new Promise<void>(resolve => {
if (document.readyState === 'complete') {
resolve();
} else {
window.addEventListener('load', () => resolve());
}
});
}
async function onActiveServiceWorker(
registration: ServiceWorkerRegistration,
): Promise<ServiceWorker> {
const serviceWorker = registration.installing || registration.waiting;
if (registration.active) {
return registration.active;
} else if (serviceWorker) {
return new Promise<ServiceWorker>(resolve => {
serviceWorker.addEventListener('statechange', () => {
if (serviceWorker.state === 'activated') {
resolve(serviceWorker);
}
});
});
}
throw new Error('Unable to locate service worker');
}
} else {
throw new Error('Service workers are not supported');
}
}