Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions .changeset/thin-horses-bake.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
---
'@builder.io/qwik-city': patch
---

FIX: Your service-worker.js won't be unregistered anymore if you added custom logic to it.

> Note: Qwik 1.14.0 and above now use `<link rel="modulepreload">` by default. If you didn't add custom service-worker logic, you should remove your service-worker.ts file(s) for the `ServiceWorkerRegister` Component to actually unregister the service-worker.js and delete its related cache. Make sure to keep the `ServiceWorkerRegister` Component in your app (without any service-worker.ts file) as long as you want to unregister the service-worker.js for your users.
Original file line number Diff line number Diff line change
Expand Up @@ -2,30 +2,48 @@ import type { BuildContext } from '../types';

export function generateServiceWorkerRegister(ctx: BuildContext, swRegister: string) {
let swReg: string;
let swUrl = '/service-worker.js';

if (ctx.isDevServer) {
// Also unregister if the developer removed the service-worker.ts file since Qwik 1.14.0 and above now use modulepreload by default
if (ctx.isDevServer || ctx.serviceWorkers.length === 0) {
swReg = SW_UNREGISTER;
} else {
swReg = swRegister;

let swUrl = '/service-worker.js';
if (ctx.serviceWorkers.length > 0) {
const sw = ctx.serviceWorkers.sort((a, b) =>
a.chunkFileName.length < b.chunkFileName.length ? -1 : 1
)[0];
swUrl = ctx.opts.basePathname + sw.chunkFileName;
}

swReg = swReg.replace('__url', swUrl);
const sw = ctx.serviceWorkers.sort((a, b) =>
a.chunkFileName.length < b.chunkFileName.length ? -1 : 1
)[0];
swUrl = ctx.opts.basePathname + sw.chunkFileName;
}
swReg = swReg.replace('__url', swUrl);

return `export default ${JSON.stringify(swReg)};`;
}

const SW_UNREGISTER = `
navigator.serviceWorker?.getRegistrations().then((regs) => {
for (const reg of regs) {
reg.unregister();
}
});
"serviceWorker"in navigator&&navigator.serviceWorker.getRegistrations().then(r=>{for(const e of r){const c='__url'.split("/").pop();e.active?.scriptURL.endsWith(c||"service-worker.js")&&e.unregister().catch(console.error)}}),"caches"in window&&caches.keys().then(r=>{const e=r.find(c=>c.startsWith("QwikBuild"));e&&caches.delete(e).catch(console.error)}).catch(console.error)
`;
// Code in SW_UNREGISTER unregisters the service worker and deletes the cache; it is the minified version of the following:
// (() => {
// if ('serviceWorker' in navigator) {
// navigator.serviceWorker.getRegistrations().then((regs) => {
// for (const reg of regs) {
// const url = '__url'.split('/').pop();
// if (reg.active?.scriptURL.endsWith(url || 'service-worker.js')) {
// reg.unregister().catch(console.error);
// }
// }
// });
// }
// if ('caches' in window) {
// caches
// .keys()
// .then((names) => {
// const cacheName = names.find((name) => name.startsWith('QwikBuild'));
// if (cacheName) {
// caches.delete(cacheName).catch(console.error);
// }
// })
// .catch(console.error);
// }
// })();
1 change: 1 addition & 0 deletions packages/qwik-city/src/buildtime/vite/plugin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -191,6 +191,7 @@ function qwikCityPlugin(userOpts?: QwikCityVitePluginOptions): any {
}
}
}

return null;
},

Expand Down
6 changes: 6 additions & 0 deletions packages/qwik-city/src/runtime/src/sw-component.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,12 @@ import type { JSXOutput } from '@builder.io/qwik';
* JS extensions are allowed) will be picked up, bundled into a separate file, and registered as a
* service worker.
*
* Qwik 1.14.0 and above now use `<link rel="modulepreload">` by default. If you didn't add custom
* service-worker logic, you should remove your service-worker.ts file(s) for the
* `ServiceWorkerRegister` Component to actually unregister the service-worker.js and delete its
* related cache. Make sure to keep the `ServiceWorkerRegister` Component in your app (without any
* service-worker.ts file) as long as you want to unregister the service-worker.js for your users.
*
* @public
*/
export const ServiceWorkerRegister = (props: { nonce?: string }): JSXOutput => (
Expand Down
35 changes: 16 additions & 19 deletions packages/qwik-city/src/runtime/src/sw-register.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,24 +2,21 @@

(() => {
if ('serviceWorker' in navigator) {
navigator.serviceWorker.getRegistrations().then((regs) => {
for (const reg of regs) {
const url = '__url'.split('/').pop();
if (reg.active?.scriptURL.endsWith(url || 'service-worker.js')) {
reg.unregister().catch(console.error);
}
}
});
}
if ('caches' in window) {
caches
.keys()
.then((names) => {
const cacheName = names.find((name) => name.startsWith('QwikBuild'));
if (cacheName) {
caches.delete(cacheName).catch(console.error);
}
})
.catch(console.error);
navigator.serviceWorker.register('__url').catch((e) => console.error(e));
// We need to delete the cache since we are using modulepreload by default in qwik 1.14 and above
if ('caches' in window) {
caches
.keys()
.then((names) => {
const cacheName = names.find((name) => name.startsWith('QwikBuild'));
if (cacheName) {
caches.delete(cacheName).catch(console.error);
}
})
.catch(console.error);
}
} else {
// eslint-disable-next-line no-console
console.log('Service worker not supported in this browser.');
}
})();
Loading