diff --git a/docs/.vitepress/config.ts b/docs/.vitepress/config.ts index b3f85676..41fff717 100644 --- a/docs/.vitepress/config.ts +++ b/docs/.vitepress/config.ts @@ -46,6 +46,10 @@ const Guide = [ text: 'Development', link: '/guide/development', }, + { + text: 'Unregister Service Worker', + link: '/guide/unregister-service-worker', + }, { text: 'FAQ', link: '/guide/faq', diff --git a/docs/guide/unregister-service-worker.md b/docs/guide/unregister-service-worker.md new file mode 100644 index 00000000..8948732d --- /dev/null +++ b/docs/guide/unregister-service-worker.md @@ -0,0 +1,28 @@ +--- +title: Unregister Service Worker | Guide +--- + +# Unregister Service Worker + +If you want to unregister the service worker from your PWA application, you only need to add `selfDestroying: true` to the plugin configuration. + +`vite-plugin-pwa` plugin will create a new special service worker and replace the existing one in your application once deployed in production: it has to be put in the place of the previous broken/unwanted service worker, with the same name. + +::: danger +It is **IMPORTANT TO NOT CHANGE ANYTHING** in the plugin configuration (especially **DO NOT CHANGE THE SERVICE WORKER NAME**), just keep the options and the PWA UI components (if included some toast/dialog for ready to work offline or prompt for update), the plugin will take care of changing the service worker and avoid interacting with the UI if configured. +::: + +In a future, if you want to add the PWA again to your application, you only need to remove the `selfDestroying` option or just disable it: `selfDestroying: false`. + +## Development + +You can also check the `selfDestroying` plugin option in the dev server with development options enabled: check [Development section](/guide/development) for more info. + +## Examples + +You have in the examples folder the `**-destroy` scripts in their corresponding `package.json`, you can try it on the development server or from the production build. + + +## Credits + +The implementation is based on this GitHub repo [Self-destroying ServiceWorker](https://github.com/NekR/self-destroying-sw), for more info read [Medium: Self-destroying ServiceWorker](https://medium.com/@nekrtemplar/self-destroying-serviceworker-73d62921d717). diff --git a/examples/preact-router/package.json b/examples/preact-router/package.json index c74808ba..a7b52530 100644 --- a/examples/preact-router/package.json +++ b/examples/preact-router/package.json @@ -3,6 +3,10 @@ "version": "0.0.0", "private": true, "scripts": { + "dev": "rimraf dev-dist && cross-env DEBUG=vite-plugin-pwa:* SW_DEV=true vite --force", + "dev-claims": "rimraf dev-dist && cross-env DEBUG=vite-plugin-pwa:* SW_DEV=true CLAIMS=true SW=true vite --force", + "dev-destroy": "rimraf dev-dist && cross-env DEBUG=vite-plugin-pwa:* SW_DESTROY=true SW_DEV=true vite --force", + "dev-claims-destroy": "rimraf dev-dist && cross-env DEBUG=vite-plugin-pwa:* SW_DESTROY=true SW_DEV=true CLAIMS=true SW=true vite --force", "start": "npm run run-build && npm run serve", "start-reloadsw": "npm run run-build-reloadsw && npm run serve", "start-claims": "npm run run-build-claims && npm run serve", @@ -10,9 +14,7 @@ "start-sw": "npm run run-build-sw && npm run serve", "start-sw-reloadsw": "npm run run-build-sw-reloadsw && npm run serve", "start-sw-claims": "npm run run-build-sw-claims && npm run serve", - "start-sw-claims-reloadsw": "npm run run-build-sw-reloadsw-claims && npm run serve", - "dev": "cross-env DEBUG=vite-plugin-pwa:* SW_DEV=true vite", - "dev-claims": "cross-env DEBUG=vite-plugin-pwa:* SW_DEV=true CLAIMS=true SW=true vite", + "start-sw-claims-reloadsw": "npm run run-build-sw-claims-reloadsw && npm run serve", "build": "rimraf dist && cross-env DEBUG=vite-plugin-pwa:* BASE_URL=/ SOURCE_MAP=true vite build", "run-build": "rimraf dist && cross-env DEBUG=vite-plugin-pwa:* BASE_URL=/ SOURCE_MAP=true vite build", "run-build-reloadsw": "rimraf dist && cross-env DEBUG=vite-plugin-pwa:* BASE_URL=/ SOURCE_MAP=true RELOAD_SW=true vite build", @@ -21,7 +23,23 @@ "run-build-sw": "rimraf dist && cross-env DEBUG=vite-plugin-pwa:* BASE_URL=/ SOURCE_MAP=true SW=true vite build", "run-build-sw-reloadsw": "cross-env DEBUG=vite-plugin-pwa:* BASE_URL=/ SOURCE_MAP=true RELOAD_SW=true SW=true vite build", "run-build-sw-claims": "cross-env DEBUG=vite-plugin-pwa:* BASE_URL=/ SOURCE_MAP=true CLAIMS=true SW=true vite build", - "run-build-sw-reloadsw-claims": "cross-env DEBUG=vite-plugin-pwa:* BASE_URL=/ SOURCE_MAP=true CLAIMS=true RELOAD_SW=true SW=true vite build", + "run-build-sw-claims-reloadsw": "cross-env DEBUG=vite-plugin-pwa:* BASE_URL=/ SOURCE_MAP=true CLAIMS=true RELOAD_SW=true SW=true vite build", + "start-destroy": "npm run run-build-destroy && npm run serve", + "start-reloadsw-destroy": "npm run run-build-reloadsw-destroy && npm run serve", + "start-claims-destroy": "npm run run-build-claims-destroy && npm run serve", + "start-claims-reloadsw-destroy": "npm run run-build-reloadsw-claims-destroy && npm run serve", + "start-sw-destroy": "npm run run-build-sw-destroy && npm run serve", + "start-sw-reloadsw-destroy": "npm run run-build-sw-reloadsw-destroy && npm run serve", + "start-sw-claims-destroy": "npm run run-build-sw-claims-destroy && npm run serve", + "start-sw-claims-reloadsw-destroy": "npm run run-build-sw-reloadsw-claims-destroy && npm run serve", + "run-build-destroy": "cross-env DEBUG=vite-plugin-pwa:* BASE_URL=/ SOURCE_MAP=true SW_DESTROY=true vite build", + "run-build-reloadsw-destroy": "cross-env DEBUG=vite-plugin-pwa:* BASE_URL=/ SOURCE_MAP=true SW_DESTROY=true RELOAD_SW=true vite build", + "run-build-claims-destroy": "cross-env DEBUG=vite-plugin-pwa:* BASE_URL=/ SOURCE_MAP=true SW_DESTROY=true CLAIMS=true vite build", + "run-build-reloadsw-claims-destroy": "cross-env DEBUG=vite-plugin-pwa:* BASE_URL=/ SOURCE_MAP=true SW_DESTROY=true CLAIMS=true RELOAD_SW=true vite build", + "run-build-sw-destroy": "rimraf dist && cross-env DEBUG=vite-plugin-pwa:* BASE_URL=/ SOURCE_MAP=true SW_DESTROY=true SW=true vite build", + "run-build-sw-reloadsw-destroy": "cross-env DEBUG=vite-plugin-pwa:* BASE_URL=/ SOURCE_MAP=true SW_DESTROY=true RELOAD_SW=true SW=true vite build", + "run-build-sw-claims-destroy": "cross-env DEBUG=vite-plugin-pwa:* BASE_URL=/ SOURCE_MAP=true SW_DESTROY=true CLAIMS=true SW=true vite build", + "run-build-sw-reloadsw-claims-destroy": "cross-env DEBUG=vite-plugin-pwa:* BASE_URL=/ SOURCE_MAP=true SW_DESTROY=true CLAIMS=true RELOAD_SW=true SW=true vite build", "serve": "serve dist" }, "dependencies": { diff --git a/examples/preact-router/vite.config.ts b/examples/preact-router/vite.config.ts index 77505276..99bda061 100644 --- a/examples/preact-router/vite.config.ts +++ b/examples/preact-router/vite.config.ts @@ -42,6 +42,7 @@ const pwaOptions: Partial = { const replaceOptions = { __DATE__: new Date().toISOString() } const claims = process.env.CLAIMS === 'true' const reload = process.env.RELOAD_SW === 'true' +const selfDestroying = process.env.SW_DESTROY === 'true' if (process.env.SW === 'true') { pwaOptions.srcDir = 'src' @@ -59,6 +60,9 @@ if (reload) { replaceOptions.__RELOAD_SW__ = 'true' } +if (selfDestroying) + pwaOptions.selfDestroying = selfDestroying + // https://vitejs.dev/config/ export default defineConfig({ // base: process.env.BASE_URL || 'https://github.com/', diff --git a/examples/react-router/package.json b/examples/react-router/package.json index c8ea6d10..abfe5dee 100644 --- a/examples/react-router/package.json +++ b/examples/react-router/package.json @@ -3,6 +3,10 @@ "version": "0.0.0", "private": true, "scripts": { + "dev": "rimraf dev-dist && cross-env DEBUG=vite-plugin-pwa:* SW_DEV=true vite --force", + "dev-claims": "rimraf dev-dist && cross-env DEBUG=vite-plugin-pwa:* SW_DEV=true CLAIMS=true SW=true vite --force", + "dev-destroy": "rimraf dev-dist && cross-env DEBUG=vite-plugin-pwa:* SW_DESTROY=true SW_DEV=true vite --force", + "dev-claims-destroy": "rimraf dev-dist && cross-env DEBUG=vite-plugin-pwa:* SW_DESTROY=true SW_DEV=true CLAIMS=true SW=true vite --force", "start": "npm run run-build && npm run serve", "start-reloadsw": "npm run run-build-reloadsw && npm run serve", "start-claims": "npm run run-build-claims && npm run serve", @@ -10,9 +14,7 @@ "start-sw": "npm run run-build-sw && npm run serve", "start-sw-reloadsw": "npm run run-build-sw-reloadsw && npm run serve", "start-sw-claims": "npm run run-build-sw-claims && npm run serve", - "start-sw-claims-reloadsw": "npm run run-build-sw-reloadsw-claims && npm run serve", - "dev": "cross-env DEBUG=vite-plugin-pwa:* SW_DEV=true vite", - "dev-claims": "cross-env DEBUG=vite-plugin-pwa:* SW_DEV=true CLAIMS=true SW=true vite", + "start-sw-claims-reloadsw": "npm run run-build-sw-claims-reloadsw && npm run serve", "build": "cross-env DEBUG=vite-plugin-pwa:* BASE_URL=/ SOURCE_MAP=true vite build", "run-build": "cross-env DEBUG=vite-plugin-pwa:* BASE_URL=/ SOURCE_MAP=true vite build", "run-build-reloadsw": "cross-env DEBUG=vite-plugin-pwa:* BASE_URL=/ SOURCE_MAP=true RELOAD_SW=true vite build", @@ -21,7 +23,23 @@ "run-build-sw": "rimraf dist && cross-env DEBUG=vite-plugin-pwa:* BASE_URL=/ SOURCE_MAP=true SW=true vite build", "run-build-sw-reloadsw": "cross-env DEBUG=vite-plugin-pwa:* BASE_URL=/ SOURCE_MAP=true RELOAD_SW=true SW=true vite build", "run-build-sw-claims": "cross-env DEBUG=vite-plugin-pwa:* BASE_URL=/ SOURCE_MAP=true CLAIMS=true SW=true vite build", - "run-build-sw-reloadsw-claims": "cross-env DEBUG=vite-plugin-pwa:* BASE_URL=/ SOURCE_MAP=true CLAIMS=true RELOAD_SW=true SW=true vite build", + "run-build-sw-claims-reloadsw": "cross-env DEBUG=vite-plugin-pwa:* BASE_URL=/ SOURCE_MAP=true CLAIMS=true RELOAD_SW=true SW=true vite build", + "start-destroy": "npm run run-build-destroy && npm run serve", + "start-reloadsw-destroy": "npm run run-build-reloadsw-destroy && npm run serve", + "start-claims-destroy": "npm run run-build-claims-destroy && npm run serve", + "start-claims-reloadsw-destroy": "npm run run-build-reloadsw-claims-destroy && npm run serve", + "start-sw-destroy": "npm run run-build-sw-destroy && npm run serve", + "start-sw-reloadsw-destroy": "npm run run-build-sw-reloadsw-destroy && npm run serve", + "start-sw-claims-destroy": "npm run run-build-sw-claims-destroy && npm run serve", + "start-sw-claims-reloadsw-destroy": "npm run run-build-sw-reloadsw-claims-destroy && npm run serve", + "run-build-destroy": "cross-env DEBUG=vite-plugin-pwa:* BASE_URL=/ SOURCE_MAP=true SW_DESTROY=true vite build", + "run-build-reloadsw-destroy": "cross-env DEBUG=vite-plugin-pwa:* BASE_URL=/ SOURCE_MAP=true SW_DESTROY=true RELOAD_SW=true vite build", + "run-build-claims-destroy": "cross-env DEBUG=vite-plugin-pwa:* BASE_URL=/ SOURCE_MAP=true SW_DESTROY=true CLAIMS=true vite build", + "run-build-reloadsw-claims-destroy": "cross-env DEBUG=vite-plugin-pwa:* BASE_URL=/ SOURCE_MAP=true SW_DESTROY=true CLAIMS=true RELOAD_SW=true vite build", + "run-build-sw-destroy": "rimraf dist && cross-env DEBUG=vite-plugin-pwa:* BASE_URL=/ SOURCE_MAP=true SW_DESTROY=true SW=true vite build", + "run-build-sw-reloadsw-destroy": "cross-env DEBUG=vite-plugin-pwa:* BASE_URL=/ SOURCE_MAP=true SW_DESTROY=true RELOAD_SW=true SW=true vite build", + "run-build-sw-claims-destroy": "cross-env DEBUG=vite-plugin-pwa:* BASE_URL=/ SOURCE_MAP=true SW_DESTROY=true CLAIMS=true SW=true vite build", + "run-build-sw-reloadsw-claims-destroy": "cross-env DEBUG=vite-plugin-pwa:* BASE_URL=/ SOURCE_MAP=true SW_DESTROY=true CLAIMS=true RELOAD_SW=true SW=true vite build", "serve": "serve dist" }, "dependencies": { diff --git a/examples/react-router/vite.config.ts b/examples/react-router/vite.config.ts index 4cee17b1..e5648b55 100644 --- a/examples/react-router/vite.config.ts +++ b/examples/react-router/vite.config.ts @@ -42,6 +42,7 @@ const pwaOptions: Partial = { const replaceOptions = { __DATE__: new Date().toISOString() } const claims = process.env.CLAIMS === 'true' const reload = process.env.RELOAD_SW === 'true' +const selfDestroying = process.env.SW_DESTROY === 'true' if (process.env.SW === 'true') { pwaOptions.srcDir = 'src' @@ -59,6 +60,9 @@ if (reload) { replaceOptions.__RELOAD_SW__ = 'true' } +if (selfDestroying) + pwaOptions.selfDestroying = selfDestroying + export default defineConfig({ // base: process.env.BASE_URL || 'https://github.com/', build: { diff --git a/examples/solid-router/package.json b/examples/solid-router/package.json index d2c3b3ed..2615141e 100644 --- a/examples/solid-router/package.json +++ b/examples/solid-router/package.json @@ -3,6 +3,10 @@ "version": "0.0.0", "private": true, "scripts": { + "dev": "rimraf dev-dist && cross-env DEBUG=vite-plugin-pwa:* SW_DEV=true vite --force", + "dev-claims": "rimraf dev-dist && cross-env DEBUG=vite-plugin-pwa:* SW_DEV=true CLAIMS=true SW=true vite --force", + "dev-destroy": "rimraf dev-dist && cross-env DEBUG=vite-plugin-pwa:* SW_DESTROY=true SW_DEV=true vite --force", + "dev-claims-destroy": "rimraf dev-dist && cross-env DEBUG=vite-plugin-pwa:* SW_DESTROY=true SW_DEV=true CLAIMS=true SW=true vite --force", "start": "npm run run-build && npm run serve", "start-reloadsw": "npm run run-build-reloadsw && npm run serve", "start-claims": "npm run run-build-claims && npm run serve", @@ -10,9 +14,7 @@ "start-sw": "npm run run-build-sw && npm run serve", "start-sw-reloadsw": "npm run run-build-sw-reloadsw && npm run serve", "start-sw-claims": "npm run run-build-sw-claims && npm run serve", - "start-sw-claims-reloadsw": "npm run run-build-sw-reloadsw-claims && npm run serve", - "dev": "cross-env DEBUG=vite-plugin-pwa:* SW_DEV=true vite", - "dev-claims": "cross-env DEBUG=vite-plugin-pwa:* SW_DEV=true CLAIMS=true SW=true vite", + "start-sw-claims-reloadsw": "npm run run-build-sw-claims-reloadsw && npm run serve", "build": "rimraf dist && cross-env DEBUG=vite-plugin-pwa:* BASE_URL=/ SOURCE_MAP=true vite build", "run-build": "rimraf dist && cross-env DEBUG=vite-plugin-pwa:* BASE_URL=/ SOURCE_MAP=true vite build", "run-build-reloadsw": "rimraf dist && cross-env DEBUG=vite-plugin-pwa:* BASE_URL=/ SOURCE_MAP=true RELOAD_SW=true vite build", @@ -21,7 +23,23 @@ "run-build-sw": "rimraf dist && cross-env DEBUG=vite-plugin-pwa:* BASE_URL=/ SOURCE_MAP=true SW=true vite build", "run-build-sw-reloadsw": "cross-env DEBUG=vite-plugin-pwa:* BASE_URL=/ SOURCE_MAP=true RELOAD_SW=true SW=true vite build", "run-build-sw-claims": "cross-env DEBUG=vite-plugin-pwa:* BASE_URL=/ SOURCE_MAP=true CLAIMS=true vite SW=true build", - "run-build-sw-reloadsw-claims": "cross-env DEBUG=vite-plugin-pwa:* BASE_URL=/ SOURCE_MAP=true CLAIMS=true RELOAD_SW=true SW=true vite build", + "run-build-sw-claims-reloadsw": "cross-env DEBUG=vite-plugin-pwa:* BASE_URL=/ SOURCE_MAP=true CLAIMS=true RELOAD_SW=true SW=true vite build", + "start-destroy": "npm run run-build-destroy && npm run serve", + "start-reloadsw-destroy": "npm run run-build-reloadsw-destroy && npm run serve", + "start-claims-destroy": "npm run run-build-claims-destroy && npm run serve", + "start-claims-reloadsw-destroy": "npm run run-build-reloadsw-claims-destroy && npm run serve", + "start-sw-destroy": "npm run run-build-sw-destroy && npm run serve", + "start-sw-reloadsw-destroy": "npm run run-build-sw-reloadsw-destroy && npm run serve", + "start-sw-claims-destroy": "npm run run-build-sw-claims-destroy && npm run serve", + "start-sw-claims-reloadsw-destroy": "npm run run-build-sw-reloadsw-claims-destroy && npm run serve", + "run-build-destroy": "cross-env DEBUG=vite-plugin-pwa:* BASE_URL=/ SOURCE_MAP=true SW_DESTROY=true vite build", + "run-build-reloadsw-destroy": "cross-env DEBUG=vite-plugin-pwa:* BASE_URL=/ SOURCE_MAP=true SW_DESTROY=true RELOAD_SW=true vite build", + "run-build-claims-destroy": "cross-env DEBUG=vite-plugin-pwa:* BASE_URL=/ SOURCE_MAP=true SW_DESTROY=true CLAIMS=true vite build", + "run-build-reloadsw-claims-destroy": "cross-env DEBUG=vite-plugin-pwa:* BASE_URL=/ SOURCE_MAP=true SW_DESTROY=true CLAIMS=true RELOAD_SW=true vite build", + "run-build-sw-destroy": "cross-env DEBUG=vite-plugin-pwa:* BASE_URL=/ SOURCE_MAP=true SW_DESTROY=true SW=true vite build", + "run-build-sw-reloadsw-destroy": "cross-env DEBUG=vite-plugin-pwa:* BASE_URL=/ SOURCE_MAP=true SW_DESTROY=true RELOAD_SW=true SW=true vite build", + "run-build-sw-claims-destroy": "cross-env DEBUG=vite-plugin-pwa:* BASE_URL=/ SOURCE_MAP=true SW_DESTROY=true CLAIMS=true SW=true vite build", + "run-build-sw-reloadsw-claims-destroy": "cross-env DEBUG=vite-plugin-pwa:* BASE_URL=/ SOURCE_MAP=true SW_DESTROY=true CLAIMS=true RELOAD_SW=true SW=true vite build", "serve": "serve dist" }, "dependencies": { diff --git a/examples/solid-router/vite.config.ts b/examples/solid-router/vite.config.ts index da99f2f6..c38be1dd 100644 --- a/examples/solid-router/vite.config.ts +++ b/examples/solid-router/vite.config.ts @@ -42,6 +42,7 @@ const pwaOptions: Partial = { const replaceOptions = { __DATE__: new Date().toISOString() } const claims = process.env.CLAIMS === 'true' const reload = process.env.RELOAD_SW === 'true' +const selfDestroying = process.env.SW_DESTROY === 'true' if (process.env.SW === 'true') { pwaOptions.srcDir = 'src' @@ -59,6 +60,9 @@ if (reload) { replaceOptions.__RELOAD_SW__ = 'true' } +if (selfDestroying) + pwaOptions.selfDestroying = selfDestroying + export default defineConfig({ build: { sourcemap: process.env.SOURCE_MAP === 'true', diff --git a/examples/svelte-routify/package.json b/examples/svelte-routify/package.json index be84ee53..1527aa54 100644 --- a/examples/svelte-routify/package.json +++ b/examples/svelte-routify/package.json @@ -4,6 +4,10 @@ "private": true, "type": "module", "scripts": { + "dev": "rimraf dev-dist && routify -b && cross-env DEBUG=vite-plugin-pwa:* SW_DEV=true vite --force", + "dev-claims": "rimraf dev-dist && routify -b && cross-env DEBUG=vite-plugin-pwa:* SW_DEV=true CLAIMS=true SW=true vite --force", + "dev-destroy": "rimraf dev-dist && routify -b && cross-env DEBUG=vite-plugin-pwa:* SW_DESTROY=true SW_DEV=true vite --force", + "dev-claims-destroy": "rimraf dev-dist && routify -b && cross-env DEBUG=vite-plugin-pwa:* SW_DESTROY=true SW_DEV=true CLAIMS=true SW=true vite --force", "start": "npm run run-build && npm run serve", "start-reloadsw": "npm run run-build-reloadsw && npm run serve", "start-claims": "npm run run-build-claims && npm run serve", @@ -11,9 +15,7 @@ "start-sw": "npm run run-build-sw && npm run serve", "start-sw-reloadsw": "npm run run-build-sw-reloadsw && npm run serve", "start-sw-claims": "npm run run-build-sw-claims && npm run serve", - "start-sw-claims-reloadsw": "npm run run-build-sw-reloadsw-claims && npm run serve", - "dev": "routify -b && cross-env DEBUG=vite-plugin-pwa:* SW_DEV=true vite", - "dev-claims": "routify -b && cross-env DEBUG=vite-plugin-pwa:* SW_DEV=true CLAIMS=true SW=true vite", + "start-sw-claims-reloadsw": "npm run run-build-sw-claims-reloadsw && npm run serve", "build": "routify -b && cross-env DEBUG=vite-plugin-pwa:* BASE_URL=/ SOURCE_MAP=true vite build", "run-build": "routify -b && cross-env DEBUG=vite-plugin-pwa:* BASE_URL=/ SOURCE_MAP=true vite build", "run-build-reloadsw": "routify -b && cross-env DEBUG=vite-plugin-pwa:* BASE_URL=/ SOURCE_MAP=true RELOAD_SW=true vite build", @@ -22,7 +24,23 @@ "run-build-sw": "rimraf dist && cross-env DEBUG=vite-plugin-pwa:* BASE_URL=/ SOURCE_MAP=true SW=true vite build", "run-build-sw-reloadsw": "cross-env DEBUG=vite-plugin-pwa:* BASE_URL=/ SOURCE_MAP=true RELOAD_SW=true vite build", "run-build-sw-claims": "cross-env DEBUG=vite-plugin-pwa:* BASE_URL=/ SOURCE_MAP=true CLAIMS=true SW=true vite build", - "run-build-sw-reloadsw-claims": "cross-env DEBUG=vite-plugin-pwa:* BASE_URL=/ SOURCE_MAP=true CLAIMS=true RELOAD_SW=true SW=true vite build", + "run-build-sw-claims-reloadsw": "cross-env DEBUG=vite-plugin-pwa:* BASE_URL=/ SOURCE_MAP=true CLAIMS=true RELOAD_SW=true SW=true vite build", + "start-destroy": "npm run run-build-destroy && npm run serve", + "start-reloadsw-destroy": "npm run run-build-reloadsw-destroy && npm run serve", + "start-claims-destroy": "npm run run-build-claims-destroy && npm run serve", + "start-claims-reloadsw-destroy": "npm run run-build-reloadsw-claims-destroy && npm run serve", + "start-sw-destroy": "npm run run-build-sw-destroy && npm run serve", + "start-sw-reloadsw-destroy": "npm run run-build-sw-reloadsw-destroy && npm run serve", + "start-sw-claims-destroy": "npm run run-build-sw-claims-destroy && npm run serve", + "start-sw-claims-reloadsw-destroy": "npm run run-build-sw-reloadsw-claims-destroy && npm run serve", + "run-build-destroy": "cross-env DEBUG=vite-plugin-pwa:* BASE_URL=/ SOURCE_MAP=true SW_DESTROY=true vite build", + "run-build-reloadsw-destroy": "cross-env DEBUG=vite-plugin-pwa:* BASE_URL=/ SOURCE_MAP=true SW_DESTROY=true RELOAD_SW=true vite build", + "run-build-claims-destroy": "cross-env DEBUG=vite-plugin-pwa:* BASE_URL=/ SOURCE_MAP=true SW_DESTROY=true CLAIMS=true vite build", + "run-build-reloadsw-claims-destroy": "cross-env DEBUG=vite-plugin-pwa:* BASE_URL=/ SOURCE_MAP=true SW_DESTROY=true CLAIMS=true RELOAD_SW=true vite build", + "run-build-sw-destroy": "rimraf dist && cross-env DEBUG=vite-plugin-pwa:* BASE_URL=/ SOURCE_MAP=true SW_DESTROY=true SW=true vite build", + "run-build-sw-reloadsw-destroy": "cross-env DEBUG=vite-plugin-pwa:* BASE_URL=/ SOURCE_MAP=true SW_DESTROY=true RELOAD_SW=true SW=true vite build", + "run-build-sw-claims-destroy": "cross-env DEBUG=vite-plugin-pwa:* BASE_URL=/ SOURCE_MAP=true SW_DESTROY=true CLAIMS=true SW=true vite build", + "run-build-sw-reloadsw-claims-destroy": "cross-env DEBUG=vite-plugin-pwa:* BASE_URL=/ SOURCE_MAP=true SW_DESTROY=true CLAIMS=true RELOAD_SW=true SW=true vite build", "serve": "serve dist" }, "devDependencies": { diff --git a/examples/svelte-routify/vite.config.js b/examples/svelte-routify/vite.config.js index bb4c948a..042a45ff 100644 --- a/examples/svelte-routify/vite.config.js +++ b/examples/svelte-routify/vite.config.js @@ -41,6 +41,7 @@ const pwaOptions = { const replaceOptions = { __DATE__: new Date().toISOString() } const claims = process.env.CLAIMS === 'true' const reload = process.env.RELOAD_SW === 'true' +const selfDestroying = process.env.SW_DESTROY === 'true' if (process.env.SW === 'true') { pwaOptions.srcDir = 'src' @@ -58,6 +59,9 @@ if (reload) { replaceOptions.__RELOAD_SW__ = 'true' } +if (selfDestroying) + pwaOptions.selfDestroying = selfDestroying + export default defineConfig({ // base: process.env.BASE_URL || 'https://github.com/', build: { diff --git a/examples/sveltekit-pwa/package.json b/examples/sveltekit-pwa/package.json index ceaf318b..5001d153 100644 --- a/examples/sveltekit-pwa/package.json +++ b/examples/sveltekit-pwa/package.json @@ -3,8 +3,10 @@ "version": "0.0.0", "private": true, "scripts": { - "dev": "cross-env DEBUG=vite-plugin-pwa:* SW_DEV=true svelte-kit dev", - "dev-claims": "cross-env DEBUG=vite-plugin-pwa:* SW_DEV=true CLAIMS=true SW=true svelte-kit dev", + "dev": "rimraf dev-dist && cross-env DEBUG=vite-plugin-pwa:* SW_DEV=true svelte-kit dev", + "dev-claims": "rimraf dev-dist && cross-env DEBUG=vite-plugin-pwa:* SW_DEV=true CLAIMS=true SW=true svelte-kit dev", + "dev-destroy": "rimraf dev-dist && cross-env DEBUG=vite-plugin-pwa:* SW_DESTROY=true SW_DEV=true svelte-kit dev", + "dev-claims-destroy": "rimraf dev-dist && cross-env DEBUG=vite-plugin-pwa:* SW_DESTROY=true SW_DEV=true CLAIMS=true SW=true svelte-kit dev", "build": "svelte-kit build", "package": "svelte-kit package", "preview": "svelte-kit preview", @@ -18,7 +20,7 @@ "start-sw": "npm run run-build-sw && npm run preview", "start-sw-reloadsw": "npm run run-build-sw-reloadsw && npm run preview", "start-sw-claims": "npm run run-build-sw-claims && npm run preview", - "start-sw-claims-reloadsw": "npm run run-build-sw-reloadsw-claims && npm run preview", + "start-sw-claims-reloadsw": "npm run run-build-sw-claims-reloadsw && npm run preview", "run-build": "rimraf .svelte-kit && rimraf build && cross-env DEBUG=vite-plugin-pwa:* BASE_URL=/ SOURCE_MAP=true svelte-kit build && node ./pwa.js --BASE_URL=/ --SOURCE_MAP=true", "run-build-reloadsw": "rimraf .svelte-kit && rimraf build && cross-env DEBUG=vite-plugin-pwa:* BASE_URL=/ SOURCE_MAP=true RELOAD_SW=true svelte-kit build && node ./pwa.js --BASE_URL=/ --SOURCE_MAP=true --RELOAD_SW=true", "run-build-claims": "rimraf .svelte-kit && rimraf build && cross-env DEBUG=vite-plugin-pwa:* BASE_URL=/ SOURCE_MAP=true CLAIMS=true svelte-kit build && node ./pwa.js --BASE_URL=/ --SOURCE_MAP=true --CLAIMS=true", @@ -26,7 +28,23 @@ "run-build-sw": "rimraf .svelte-kit && rimraf build && cross-env DEBUG=vite-plugin-pwa:* BASE_URL=/ SOURCE_MAP=true SW=true svelte-kit build && node ./pwa.js --BASE_URL=/ --SOURCE_MAP=true --SW=true", "run-build-sw-reloadsw": "rimraf .svelte-kit && rimraf build && cross-env DEBUG=vite-plugin-pwa:* BASE_URL=/ SOURCE_MAP=true RELOAD_SW=true SW=true svelte-kit build && node ./pwa.js --BASE_URL=/ --SOURCE_MAP=true --RELOAD_SW=true --SW=true", "run-build-sw-claims": "rimraf .svelte-kit && rimraf build && cross-env DEBUG=vite-plugin-pwa:* BASE_URL=/ SOURCE_MAP=true CLAIMS=true SW=true svelte-kit build && node ./pwa.js --BASE_URL=/ --SOURCE_MAP=true --CLAIMS=true --SW=true", - "run-build-sw-reloadsw-claims": "rimraf .svelte-kit && rimraf build && cross-env DEBUG=vite-plugin-pwa:* BASE_URL=/ SOURCE_MAP=true CLAIMS=true RELOAD_SW=true SW=true svelte-kit build && node ./pwa.js --BASE_URL=/ --SOURCE_MAP=true --CLAIMS=true --RELOAD_SW=true --SW=true" + "run-build-sw-claims-reloadsw": "rimraf .svelte-kit && rimraf build && cross-env DEBUG=vite-plugin-pwa:* BASE_URL=/ SOURCE_MAP=true CLAIMS=true RELOAD_SW=true SW=true svelte-kit build && node ./pwa.js --BASE_URL=/ --SOURCE_MAP=true --CLAIMS=true --RELOAD_SW=true --SW=true", + "start-destroy": "npm run run-build-destroy && npm run preview", + "start-reloadsw-destroy": "npm run run-build-reloadsw-destroy && npm run preview", + "start-claims-destroy": "npm run run-build-claims-destroy && npm run preview", + "start-claims-reloadsw-destroy": "npm run run-build-reloadsw-claims-destroy && npm run preview", + "start-sw-destroy": "npm run run-build-sw-destroy && npm run preview", + "start-sw-reloadsw-destroy": "npm run run-build-sw-reloadsw-destroy && npm run preview", + "start-sw-claims-destroy": "npm run run-build-sw-claims-destroy && npm run preview", + "start-sw-claims-reloadsw-destroy": "npm run run-build-sw-reloadsw-claims-destroy && npm run preview", + "run-build-destroy": "rimraf .svelte-kit && rimraf build && cross-env DEBUG=vite-plugin-pwa:* BASE_URL=/ SOURCE_MAP=true SW_DESTROY=true svelte-kit build && node ./pwa.js --BASE_URL=/ --SOURCE_MAP=true --SW_DESTROY=true", + "run-build-reloadsw-destroy": "rimraf .svelte-kit && rimraf build && cross-env DEBUG=vite-plugin-pwa:* BASE_URL=/ SOURCE_MAP=true SW_DESTROY=true RELOAD_SW=true svelte-kit build && node ./pwa.js --BASE_URL=/ --SOURCE_MAP=true --SW_DESTROY=true --RELOAD_SW=true", + "run-build-claims-destroy": "rimraf .svelte-kit && rimraf build && cross-env DEBUG=vite-plugin-pwa:* BASE_URL=/ SOURCE_MAP=true SW_DESTROY=true CLAIMS=true svelte-kit build && node ./pwa.js --BASE_URL=/ --SOURCE_MAP=true --SW_DESTROY=true --CLAIMS=true", + "run-build-reloadsw-claims-destroy": "rimraf .svelte-kit && rimraf build && cross-env DEBUG=vite-plugin-pwa:* BASE_URL=/ SOURCE_MAP=true SW_DESTROY=true CLAIMS=true RELOAD_SW=true svelte-kit build && node ./pwa.js --BASE_URL=/ --SOURCE_MAP=true --SW_DESTROY=true --CLAIMS=true --RELOAD_SW=true", + "run-build-sw-destroy": "rimraf .svelte-kit && rimraf build && cross-env DEBUG=vite-plugin-pwa:* BASE_URL=/ SOURCE_MAP=true SW_DESTROY=true SW=true svelte-kit build && node ./pwa.js --BASE_URL=/ --SOURCE_MAP=true --SW_DESTROY=true --SW=true", + "run-build-sw-reloadsw-destroy": "rimraf .svelte-kit && rimraf build && cross-env DEBUG=vite-plugin-pwa:* BASE_URL=/ SOURCE_MAP=true SW_DESTROY=true RELOAD_SW=true SW=true svelte-kit build && node ./pwa.jss --BASE_URL=/ --SOURCE_MAP=true --SW_DESTROY=true --RELOAD_SW=true --SW=true", + "run-build-sw-claims-destroy": "rimraf .svelte-kit && rimraf build && cross-env DEBUG=vite-plugin-pwa:* BASE_URL=/ SOURCE_MAP=true SW_DESTROY=true CLAIMS=true SW=true svelte-kit build && node ./pwa.js --BASE_URL=/ --SOURCE_MAP=true --SW_DESTROY=true --CLAIMS=true --SW=true", + "run-build-sw-reloadsw-claims-destroy": "rimraf .svelte-kit && rimraf build && cross-env DEBUG=vite-plugin-pwa:* BASE_URL=/ SOURCE_MAP=true SW_DESTROY=true CLAIMS=true RELOAD_SW=true SW=true svelte-kit build && node ./pwa.js --BASE_URL=/ --SOURCE_MAP=true --SW_DESTROY=true --CLAIMS=true --RELOAD_SW=true --SW=true" }, "devDependencies": { "@rollup/plugin-replace": "^4.0.0", diff --git a/examples/sveltekit-pwa/pwa-configuration.js b/examples/sveltekit-pwa/pwa-configuration.js index 0892b6cc..82d5f2d8 100644 --- a/examples/sveltekit-pwa/pwa-configuration.js +++ b/examples/sveltekit-pwa/pwa-configuration.js @@ -44,6 +44,7 @@ const pwaConfiguration = { const claims = process.env.CLAIMS === 'true' const reload = process.env.RELOAD_SW === 'true' const sw = process.env.SW === 'true' +const selfDestroying = process.env.SW_DESTROY === 'true' const replaceOptions = { __DATE__: new Date().toISOString(), __RELOAD_SW__: reload ? 'true' : 'false', @@ -94,4 +95,7 @@ if (sw) { if (claims) pwaConfiguration.registerType = 'autoUpdate' +if (selfDestroying) + pwaConfiguration.selfDestroying = selfDestroying + export { pwaConfiguration, replaceOptions } diff --git a/examples/vanilla-ts-dev-options/README.md b/examples/vanilla-ts-dev-options/README.md new file mode 100644 index 00000000..8d2c3fa4 --- /dev/null +++ b/examples/vanilla-ts-dev-options/README.md @@ -0,0 +1,9 @@ +# Example + +This example relies on [https-localhost](https://github.com/daquinoaldo/https-localhost) to serve the dist files on https://localhost/. Please refer to it's docs for the steps to setup your local environment. + +```bash +npm run start +``` + +Open up https://localhost/, then restart the server, you will see a notification ask you to restart reload the offline content. diff --git a/examples/vanilla-ts-dev-options/index.html b/examples/vanilla-ts-dev-options/index.html new file mode 100644 index 00000000..3b056a5b --- /dev/null +++ b/examples/vanilla-ts-dev-options/index.html @@ -0,0 +1,22 @@ + + + + + + + + + + + Vite App + + + +
+ + + diff --git a/examples/vanilla-ts-dev-options/package.json b/examples/vanilla-ts-dev-options/package.json new file mode 100644 index 00000000..a5400dba --- /dev/null +++ b/examples/vanilla-ts-dev-options/package.json @@ -0,0 +1,22 @@ +{ + "name": "vanilla-ts-dev-options", + "version": "0.0.0", + "private": true, + "scripts": { + "dev-auto": "rimraf dev-dist && cross-env DEBUG=vite-plugin-pwa:* SW_DEV=true SW_INLINE=auto vite --force", + "dev-inline": "rimraf dev-dist && cross-env DEBUG=vite-plugin-pwa:* SW_DEV=true SW_INLINE=inline vite --force", + "dev-script": "rimraf dev-dist && cross-env DEBUG=vite-plugin-pwa:* SW_DEV=true SW_INLINE=script vite --force", + "dev-auto-destroy": "rimraf dev-dist && cross-env DEBUG=vite-plugin-pwa:* SW_DEV=true SW_DESTROY=true SW_INLINE=auto vite --force", + "dev-inline-destroy": "rimraf dev-dist && cross-env DEBUG=vite-plugin-pwa:* SW_DEV=true SW_DESTROY=true SW_INLINE=inline vite --force", + "dev-script-destroy": "rimraf dev-dist && cross-env DEBUG=vite-plugin-pwa:* SW_DEV=true SW_DESTROY=true SW_INLINE=script vite --force", + "build": "cross-env DEBUG=vite-plugin-pwa:* vite build", + "serve": "serve dist" + }, + "devDependencies": { + "cross-env": "^7.0.3", + "rimraf": "^3.0.2", + "typescript": "^4.7.4", + "vite": "^2.9.13", + "vite-plugin-pwa": "workspace:*" + } +} diff --git a/examples/vanilla-ts-dev-options/public/favicon.svg b/examples/vanilla-ts-dev-options/public/favicon.svg new file mode 100644 index 00000000..733f4fb4 --- /dev/null +++ b/examples/vanilla-ts-dev-options/public/favicon.svg @@ -0,0 +1,130 @@ + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/examples/vanilla-ts-dev-options/public/pwa-192x192.png b/examples/vanilla-ts-dev-options/public/pwa-192x192.png new file mode 100644 index 00000000..cd3ee45e Binary files /dev/null and b/examples/vanilla-ts-dev-options/public/pwa-192x192.png differ diff --git a/examples/vanilla-ts-dev-options/public/pwa-512x512.png b/examples/vanilla-ts-dev-options/public/pwa-512x512.png new file mode 100644 index 00000000..200cb73a Binary files /dev/null and b/examples/vanilla-ts-dev-options/public/pwa-512x512.png differ diff --git a/examples/vanilla-ts-dev-options/src/main.ts b/examples/vanilla-ts-dev-options/src/main.ts new file mode 100644 index 00000000..85509f0f --- /dev/null +++ b/examples/vanilla-ts-dev-options/src/main.ts @@ -0,0 +1,7 @@ +document.querySelector('#app')!.innerHTML = ` +
+ PWA Logo +

Vite + TypeScript

+

Testing SW with injectRegister=auto,inline,script

+
+` diff --git a/examples/vanilla-ts-dev-options/src/vite-env.ts b/examples/vanilla-ts-dev-options/src/vite-env.ts new file mode 100644 index 00000000..64251fba --- /dev/null +++ b/examples/vanilla-ts-dev-options/src/vite-env.ts @@ -0,0 +1,2 @@ +/// +/// diff --git a/examples/vanilla-ts-dev-options/tsconfig.json b/examples/vanilla-ts-dev-options/tsconfig.json new file mode 100644 index 00000000..fbd02253 --- /dev/null +++ b/examples/vanilla-ts-dev-options/tsconfig.json @@ -0,0 +1,20 @@ +{ + "compilerOptions": { + "target": "ESNext", + "useDefineForClassFields": true, + "module": "ESNext", + "lib": ["ESNext", "DOM"], + "moduleResolution": "Node", + "strict": true, + "sourceMap": true, + "resolveJsonModule": true, + "isolatedModules": true, + "esModuleInterop": true, + "noEmit": true, + "noUnusedLocals": true, + "noUnusedParameters": true, + "noImplicitReturns": true, + "skipLibCheck": true + }, + "include": ["src"] +} diff --git a/examples/vanilla-ts-dev-options/vite.config.ts b/examples/vanilla-ts-dev-options/vite.config.ts new file mode 100644 index 00000000..f1711be7 --- /dev/null +++ b/examples/vanilla-ts-dev-options/vite.config.ts @@ -0,0 +1,48 @@ +import { defineConfig } from 'vite' +import { VitePWA } from 'vite-plugin-pwa' + +const injectRegister = (process.env.SW_INLINE ?? 'auto') as 'inline' | 'auto' | 'script' +const selfDestroying = process.env.SW_DESTROY === 'true' + +export default defineConfig({ + build: { + sourcemap: process.env.SOURCE_MAP === 'true', + }, + plugins: [ + VitePWA({ + mode: 'development', + base: '/', + includeAssets: ['favicon.svg'], + injectRegister, + selfDestroying, + manifest: { + name: 'PWA Router', + short_name: 'PWA Router', + theme_color: '#ffffff', + icons: [ + { + src: 'pwa-192x192.png', // <== don't add slash, for testing + sizes: '192x192', + type: 'image/png', + }, + { + src: '/pwa-512x512.png', // <== don't remove slash, for testing + sizes: '512x512', + type: 'image/png', + }, + { + src: 'pwa-512x512.png', // <== don't add slash, for testing + sizes: '512x512', + type: 'image/png', + purpose: 'any maskable', + }, + ], + }, + devOptions: { + enabled: process.env.SW_DEV === 'true', + /* when using generateSW the PWA plugin will switch to classic */ + navigateFallback: 'index.html', + }, + }), + ], +}) diff --git a/examples/vue-router/package.json b/examples/vue-router/package.json index 7811c7d7..39398011 100644 --- a/examples/vue-router/package.json +++ b/examples/vue-router/package.json @@ -3,6 +3,10 @@ "version": "0.0.0", "private": true, "scripts": { + "dev": "rimraf dev-dist && cross-env DEBUG=vite-plugin-pwa:* SW_DEV=true vite --force", + "dev-claims": "rimraf dev-dist && cross-env DEBUG=vite-plugin-pwa:* SW_DEV=true CLAIMS=true SW=true vite --force", + "dev-destroy": "rimraf dev-dist && cross-env DEBUG=vite-plugin-pwa:* SW_DESTROY=true SW_DEV=true vite --force", + "dev-claims-destroy": "rimraf dev-dist && cross-env DEBUG=vite-plugin-pwa:* SW_DESTROY=true SW_DEV=true CLAIMS=true SW=true vite --force", "start": "npm run run-build && npm run serve", "start-reloadsw": "npm run run-build-reloadsw && npm run serve", "start-claims": "npm run run-build-claims && npm run serve", @@ -10,9 +14,7 @@ "start-sw": "npm run run-build-sw && npm run serve", "start-sw-reloadsw": "npm run run-build-sw-reloadsw && npm run serve", "start-sw-claims": "npm run run-build-sw-claims && npm run serve", - "start-sw-claims-reloadsw": "npm run run-build-sw-reloadsw-claims && npm run serve", - "dev": "cross-env DEBUG=vite-plugin-pwa:* SW_DEV=true vite", - "dev-claims": "cross-env DEBUG=vite-plugin-pwa:* SW_DEV=true CLAIMS=true SW=true vite", + "start-sw-claims-reloadsw": "npm run run-build-sw-claims-reloadsw && npm run serve", "build": "cross-env DEBUG=vite-plugin-pwa:* vite build", "run-build": "cross-env DEBUG=vite-plugin-pwa:* BASE_URL=/ SOURCE_MAP=true vite build", "run-build-reloadsw": "cross-env DEBUG=vite-plugin-pwa:* BASE_URL=/ SOURCE_MAP=true RELOAD_SW=true vite build", @@ -21,7 +23,23 @@ "run-build-sw": "rimraf dist && cross-env DEBUG=vite-plugin-pwa:* BASE_URL=/ SOURCE_MAP=true SW=true vite build", "run-build-sw-reloadsw": "cross-env DEBUG=vite-plugin-pwa:* BASE_URL=/ SOURCE_MAP=true RELOAD_SW=true SW=true vite build", "run-build-sw-claims": "cross-env DEBUG=vite-plugin-pwa:* BASE_URL=/ SOURCE_MAP=true CLAIMS=true SW=true vite build", - "run-build-sw-reloadsw-claims": "cross-env DEBUG=vite-plugin-pwa:* BASE_URL=/ SOURCE_MAP=true CLAIMS=true RELOAD_SW=true SW=true vite build", + "run-build-sw-claims-reloadsw": "cross-env DEBUG=vite-plugin-pwa:* BASE_URL=/ SOURCE_MAP=true CLAIMS=true RELOAD_SW=true SW=true vite build", + "start-destroy": "npm run run-build-destroy && npm run serve", + "start-reloadsw-destroy": "npm run run-build-reloadsw-destroy && npm run serve", + "start-claims-destroy": "npm run run-build-claims-destroy && npm run serve", + "start-claims-reloadsw-destroy": "npm run run-build-reloadsw-claims-destroy && npm run serve", + "start-sw-destroy": "npm run run-build-sw-destroy && npm run serve", + "start-sw-reloadsw-destroy": "npm run run-build-sw-reloadsw-destroy && npm run serve", + "start-sw-claims-destroy": "npm run run-build-sw-claims-destroy && npm run serve", + "start-sw-claims-reloadsw-destroy": "npm run run-build-sw-reloadsw-claims-destroy && npm run serve", + "run-build-destroy": "cross-env DEBUG=vite-plugin-pwa:* BASE_URL=/ SOURCE_MAP=true SW_DESTROY=true vite build", + "run-build-reloadsw-destroy": "cross-env DEBUG=vite-plugin-pwa:* BASE_URL=/ SOURCE_MAP=true SW_DESTROY=true RELOAD_SW=true vite build", + "run-build-claims-destroy": "cross-env DEBUG=vite-plugin-pwa:* BASE_URL=/ SOURCE_MAP=true SW_DESTROY=true CLAIMS=true vite build", + "run-build-reloadsw-claims-destroy": "cross-env DEBUG=vite-plugin-pwa:* BASE_URL=/ SOURCE_MAP=true SW_DESTROY=true CLAIMS=true RELOAD_SW=true vite build", + "run-build-sw-destroy": "rimraf dist && cross-env DEBUG=vite-plugin-pwa:* BASE_URL=/ SOURCE_MAP=true SW_DESTROY=true SW=true vite build", + "run-build-sw-reloadsw-destroy": "cross-env DEBUG=vite-plugin-pwa:* BASE_URL=/ SOURCE_MAP=true SW_DESTROY=true RELOAD_SW=true SW=true vite build", + "run-build-sw-claims-destroy": "cross-env DEBUG=vite-plugin-pwa:* BASE_URL=/ SOURCE_MAP=true SW_DESTROY=true CLAIMS=true SW=true vite build", + "run-build-sw-reloadsw-claims-destroy": "cross-env DEBUG=vite-plugin-pwa:* BASE_URL=/ SOURCE_MAP=true SW_DESTROY=true CLAIMS=true RELOAD_SW=true SW=true vite build", "serve": "serve dist" }, "dependencies": { diff --git a/examples/vue-router/vite.config.ts b/examples/vue-router/vite.config.ts index e3b1c8c5..0ffd1af4 100644 --- a/examples/vue-router/vite.config.ts +++ b/examples/vue-router/vite.config.ts @@ -42,6 +42,7 @@ const pwaOptions: Partial = { const replaceOptions = { __DATE__: new Date().toISOString() } const claims = process.env.CLAIMS === 'true' const reload = process.env.RELOAD_SW === 'true' +const selfDestroying = process.env.SW_DESTROY === 'true' if (process.env.SW === 'true') { pwaOptions.srcDir = 'src' @@ -59,6 +60,9 @@ if (reload) { replaceOptions.__RELOAD_SW__ = 'true' } +if (selfDestroying) + pwaOptions.selfDestroying = selfDestroying + export default defineConfig({ // base: process.env.BASE_URL || 'https://github.com/', build: { diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index aed4c378..f06a0c88 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -276,7 +276,7 @@ importers: devDependencies: '@rollup/plugin-replace': 4.0.0 '@sveltejs/adapter-static': 1.0.0-next.34 - '@sveltejs/kit': 1.0.0-next.357_svelte@3.48.0 + '@sveltejs/kit': 1.0.0-next.360_svelte@3.48.0 '@typescript-eslint/eslint-plugin': 5.30.3_xuuykav7urhdozug7htlfgar3u '@typescript-eslint/parser': 5.30.3_4x5o4skxv6sl53vpwefgt23khm cross-env: 7.0.3 @@ -295,6 +295,20 @@ importers: workbox-precaching: 6.5.3 workbox-routing: 6.5.3 + examples/vanilla-ts-dev-options: + specifiers: + cross-env: ^7.0.3 + rimraf: ^3.0.2 + typescript: ^4.7.4 + vite: ^2.9.13 + vite-plugin-pwa: workspace:* + devDependencies: + cross-env: 7.0.3 + rimraf: 3.0.2 + typescript: 4.7.4 + vite: 2.9.13 + vite-plugin-pwa: link:../.. + examples/vue-basic-cdn: specifiers: '@rollup/plugin-replace': ^4.0.0 @@ -2556,23 +2570,42 @@ packages: tiny-glob: 0.2.9 dev: true - /@sveltejs/kit/1.0.0-next.357_svelte@3.48.0: - resolution: {integrity: sha512-nCAehVybIEpQNnPu61V/EFVdfDb1nBSiQUfW9EcSSDEUbyAMCVBOKZZuzQ0qQDp3xniqRkyDzpBA4wN+ADxHBw==} + /@sveltejs/kit/1.0.0-next.360_svelte@3.48.0: + resolution: {integrity: sha512-z1W6oYSmDzYcjlXANkbsb0N0IS/0aDl0huzDGRZWXobis4VmzoqzOyxsczyvxwH6FWxQBXls5wNrtm6drzsr6A==} engines: {node: '>=16.7'} hasBin: true peerDependencies: svelte: ^3.44.0 + vite: ^2.9.10 dependencies: - '@sveltejs/vite-plugin-svelte': 1.0.0-next.49_svelte@3.48.0+vite@2.9.13 + '@sveltejs/vite-plugin-svelte': 1.0.0-next.49_svelte@3.48.0 chokidar: 3.5.3 sade: 1.8.1 svelte: 3.48.0 - vite: 2.9.13 transitivePeerDependencies: - diff-match-patch - - less - - sass - - stylus + - supports-color + dev: true + + /@sveltejs/vite-plugin-svelte/1.0.0-next.49_svelte@3.48.0: + resolution: {integrity: sha512-AKh0Ka8EDgidnxWUs8Hh2iZLZovkETkefO99XxZ4sW4WGJ7VFeBx5kH/NIIGlaNHLcrIvK3CK0HkZwC3Cici0A==} + engines: {node: ^14.13.1 || >= 16} + peerDependencies: + diff-match-patch: ^1.0.5 + svelte: ^3.44.0 + vite: ^2.9.0 + peerDependenciesMeta: + diff-match-patch: + optional: true + dependencies: + '@rollup/pluginutils': 4.2.1 + debug: 4.3.4 + deepmerge: 4.2.2 + kleur: 4.1.4 + magic-string: 0.26.2 + svelte: 3.48.0 + svelte-hmr: 0.14.12_svelte@3.48.0 + transitivePeerDependencies: - supports-color dev: true @@ -3811,7 +3844,7 @@ packages: safe-buffer: 5.1.2 /cookie-signature/1.0.6: - resolution: {integrity: sha1-4wOogrNCzD7oylE6eZmXNNqzriw=} + resolution: {integrity: sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==} dev: true /cookie/0.4.0: @@ -3827,7 +3860,7 @@ packages: dev: false /core-util-is/1.0.2: - resolution: {integrity: sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=} + resolution: {integrity: sha512-3lqz5YjWTYnW6dlDa5TLaTCcShfar1e40rmcJVwCBJC6mWlFuj0eCHIElmG1g5kyuJ/GD+8Wn4FFCcz4gJPfaQ==} dev: true /cors/2.8.5: @@ -3990,7 +4023,7 @@ packages: dev: true /depd/1.1.2: - resolution: {integrity: sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=} + resolution: {integrity: sha512-7emPTl6Dpo6JRXOXjLRxck+FlLRX5847cLKEn00PLAgc3g2hTZZgr+e4c2v6QpSmLeFP3n5yUo7ft6avBK/5jQ==} engines: {node: '>= 0.6'} dev: true @@ -3999,7 +4032,7 @@ packages: dev: true /destroy/1.0.4: - resolution: {integrity: sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA=} + resolution: {integrity: sha512-3NdhDuEXnfun/z7x9GOElY49LoqVHoGScmOKwmxhsS8N5Y+Z8KyPPDnaSzqWgYt/ji4mqwfTS34Htrk0zPIXVg==} dev: true /detect-indent/6.1.0: @@ -4095,7 +4128,7 @@ packages: resolution: {integrity: sha512-NcGkBVXePiuUrPLV8IxP43n1EOtdg+dudVjrfVEUd/bOqpQUFZ2diL5PPYzbgEhZFEltdXV3AcyKwGnEQ5lhMA==} /encodeurl/1.0.2: - resolution: {integrity: sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k=} + resolution: {integrity: sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==} engines: {node: '>= 0.8'} dev: true @@ -4393,7 +4426,7 @@ packages: engines: {node: '>=6'} /escape-html/1.0.3: - resolution: {integrity: sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg=} + resolution: {integrity: sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==} dev: true /escape-string-regexp/1.0.5: @@ -4880,7 +4913,7 @@ packages: engines: {node: '>=0.10.0'} /etag/1.8.1: - resolution: {integrity: sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc=} + resolution: {integrity: sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==} engines: {node: '>= 0.6'} dev: true @@ -5041,7 +5074,7 @@ packages: dev: true /forwarded/0.1.2: - resolution: {integrity: sha1-mMI9qxF1ZXuMBXPozszZGw/xjIQ=} + resolution: {integrity: sha512-Ua9xNhH0b8pwE3yRbFfXJvfdWF0UHNCdeyb2sbi9Ul/M+r3PTdrz7Cv4SCfZRMjmzEM9PhraqfZFbGTIg3OMyA==} engines: {node: '>= 0.6'} dev: true @@ -5154,7 +5187,7 @@ packages: fs.realpath: 1.0.0 inflight: 1.0.6 inherits: 2.0.4 - minimatch: 3.0.4 + minimatch: 3.1.2 once: 1.4.0 path-is-absolute: 1.0.1 @@ -5246,7 +5279,7 @@ packages: dev: true /hpack.js/2.1.6: - resolution: {integrity: sha1-h3dMCUnlE/QuhFdbPEVoH63ioLI=} + resolution: {integrity: sha512-zJxVehUdMGIKsRaNt7apO2Gqp0BdqW5yaiGHXXmbpvxgBYVZnAql+BJb4RO5ad2MgpbZKn5G6nMnegrH1FcNYQ==} dependencies: inherits: 2.0.4 obuf: 1.1.2 @@ -5275,7 +5308,7 @@ packages: dev: true /http-deceiver/1.2.7: - resolution: {integrity: sha1-+nFolEq5pRnTN8sL7HKE3D5yPYc=} + resolution: {integrity: sha512-LmpOGxTfbpgtGVxJrj5k7asXHCgNZp5nLfp+hWc8QQRqtb7fUy6kRY3BO1h9ddF6yIPYUARgxGOwB42DnxIaNw==} dev: true /http-errors/1.7.2: @@ -5401,7 +5434,7 @@ packages: wrappy: 1.0.2 /inherits/2.0.3: - resolution: {integrity: sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=} + resolution: {integrity: sha512-x00IRNXNy63jwGkJmzPigoySHbaqpNuzKbBOmzK+g2OdZpQ9w+sxCN+VSB3ja7IAge2OP2qpfxTjeNcyjmW1uw==} dev: true /inherits/2.0.4: @@ -5558,7 +5591,7 @@ packages: dev: true /isarray/1.0.0: - resolution: {integrity: sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=} + resolution: {integrity: sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==} dev: true /isexe/2.0.0: @@ -5892,7 +5925,7 @@ packages: engines: {node: '>= 8'} /methods/1.1.2: - resolution: {integrity: sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4=} + resolution: {integrity: sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==} engines: {node: '>= 0.6'} dev: true @@ -5944,11 +5977,6 @@ packages: resolution: {integrity: sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A==} dev: true - /minimatch/3.0.4: - resolution: {integrity: sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==} - dependencies: - brace-expansion: 1.1.11 - /minimatch/3.1.2: resolution: {integrity: sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==} dependencies: @@ -6149,7 +6177,7 @@ packages: dev: true /on-finished/2.3.0: - resolution: {integrity: sha1-IPEzZIGwg811M3mSoWlxqi2QaUc=} + resolution: {integrity: sha512-ikqdkGAAyf/X/gPhXGvfgAytDZtDbr+bkNUJ0N9h5MI/dmdgCs3l6hoHrcUv41sRKew3jIwrp4qQDXiK99Utww==} engines: {node: '>= 0.8'} dependencies: ee-first: 1.1.1 @@ -6308,7 +6336,7 @@ packages: resolution: {integrity: sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==} /path-to-regexp/0.1.7: - resolution: {integrity: sha1-32BBeABfUi8V60SQ5yR6G/qmf4w=} + resolution: {integrity: sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ==} dev: true /path-type/4.0.0: @@ -6764,7 +6792,7 @@ packages: dev: false /select-hose/2.0.0: - resolution: {integrity: sha1-Yl2GWPhlr0Psliv8N2o3NZpJlMo=} + resolution: {integrity: sha512-mEugaLK+YfkijB4fx0e6kImuJdCIt2LxCRcbEYPqRGCs4F2ogyfZU5IAZRdjCP8JPq2AtdNoC/Dux63d9Kiryg==} dev: true /semver/5.7.1: @@ -6995,7 +7023,7 @@ packages: dev: true /statuses/1.5.0: - resolution: {integrity: sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow=} + resolution: {integrity: sha512-OpZ3zP+jT1PI7I8nemJX4AKmAX070ZkYPVWV/AaKTJl+tXCTGyVdC1a4SL8RUQYEwk/f34ZX8UTykN68FwrqAA==} engines: {node: '>= 0.6'} dev: true @@ -7526,7 +7554,7 @@ packages: dev: true /unpipe/1.0.0: - resolution: {integrity: sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw=} + resolution: {integrity: sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==} engines: {node: '>= 0.8'} dev: true @@ -7604,7 +7632,7 @@ packages: dev: true /util-deprecate/1.0.2: - resolution: {integrity: sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=} + resolution: {integrity: sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==} dev: true /utils-merge/1.0.1: @@ -7624,7 +7652,7 @@ packages: dev: true /vary/1.1.2: - resolution: {integrity: sha1-IpnwLG3tMNSllhsLn3RSShj2NPw=} + resolution: {integrity: sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==} engines: {node: '>= 0.8'} dev: true @@ -7983,7 +8011,7 @@ packages: workbox-core: 6.5.3 /wrappy/1.0.2: - resolution: {integrity: sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=} + resolution: {integrity: sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==} /ws/7.5.3_olxz6bwltfka3jtzzpy366rsky: resolution: {integrity: sha512-kQ/dHIzuLrS6Je9+uv81ueZomEwH0qVYstcAQ4/Z93K8zeko9gtAbttJWzoC5ukqXY1PpoouV3+VSOqEAFt5wg==} diff --git a/scripts/run-examples.ts b/scripts/run-examples.ts index 790e6061..062b5255 100644 --- a/scripts/run-examples.ts +++ b/scripts/run-examples.ts @@ -94,11 +94,12 @@ interface PromptResult { strategy: Strategy behavior: Behavior reloadSW: boolean + selfDestroying: boolean } async function init() { try { - const { framework, strategy, behavior, reloadSW }: PromptResult = await prompts([ + const { framework, strategy, behavior, reloadSW, selfDestroying }: PromptResult = await prompts([ { type: 'select', name: 'framework', @@ -149,6 +150,14 @@ async function init() { active: 'yes', inactive: 'no', }, + { + type: 'toggle', + name: 'selfDestroying', + message: reset('Unregister SW?'), + initial: false, + active: 'yes', + inactive: 'no', + }, ], { onCancel: () => { @@ -172,6 +181,9 @@ async function init() { if (reloadSW) script += '-reloadsw' + if (selfDestroying) + script += '-destroy' + execSync(`pnpm run start${script}`, { stdio: 'inherit', cwd: `examples/${framework.dir}`, diff --git a/src/client/build/register.ts b/src/client/build/register.ts index 6c24c64e..1d87c5d4 100644 --- a/src/client/build/register.ts +++ b/src/client/build/register.ts @@ -3,10 +3,15 @@ import type { RegisterSWOptions } from '../type' // __SW_AUTO_UPDATE__ will be replaced by virtual module const autoUpdateMode = '__SW_AUTO_UPDATE__' +// __SW_SELF_DESTROYING__ will be replaced by virtual module +const selfDestroying = '__SW_SELF_DESTROYING__' // eslint-disable-next-line @typescript-eslint/prefer-ts-expect-error // @ts-ignore replace at build const auto = autoUpdateMode === 'true' +// eslint-disable-next-line @typescript-eslint/prefer-ts-expect-error +// @ts-ignore replace at build time +const autoDestroy = selfDestroying === 'true' export type { RegisterSWOptions } @@ -54,7 +59,7 @@ export function registerSW(options: RegisterSWOptions = {}) { // worker was controlling the page when this version was registered. if (event.isUpdate) auto && window.location.reload() - else + else if (!autoDestroy) onOfflineReady?.() }) diff --git a/src/html.ts b/src/html.ts index b5783651..8dd61610 100644 --- a/src/html.ts +++ b/src/html.ts @@ -3,6 +3,11 @@ import type { ResolvedVitePWAOptions } from './types' export function generateSimpleSWRegister(options: ResolvedVitePWAOptions, dev: boolean) { const path = dev ? `${options.base}${DEV_SW_NAME}` : `${options.base}${options.filename}` + + // we are using HMR to load this script: DO NOT ADD window::load event listener + if (dev) + return `if('serviceWorker' in navigator) navigator.serviceWorker.register('${path}', { scope: '${options.scope}' })` + return ` if('serviceWorker' in navigator) { window.addEventListener('load', () => { @@ -22,18 +27,20 @@ export function injectServiceWorker(html: string, options: ResolvedVitePWAOption manifest = options.manifest ? `` : '' } - if (options.injectRegister === 'inline') { - return html.replace( - '', - `${manifest}`, - ) - } + if (!dev) { + if (options.injectRegister === 'inline') { + return html.replace( + '', + `${manifest}`, + ) + } - if (options.injectRegister === 'script') { - return html.replace( - '', - `${manifest}`, - ) + if (options.injectRegister === 'script') { + return html.replace( + '', + `${manifest}`, + ) + } } return html.replace( diff --git a/src/modules.ts b/src/modules.ts index 5c30f508..6793ad03 100644 --- a/src/modules.ts +++ b/src/modules.ts @@ -24,10 +24,35 @@ export async function generateRegisterSW(options: ResolvedVitePWAOptions, mode: .replace('__SW__', sw) .replace('__SCOPE__', scope) .replace('__SW_AUTO_UPDATE__', `${options.registerType === 'autoUpdate'}`) + .replace('__SW_SELF_DESTROYING__', `${options.selfDestroying}`) .replace('__TYPE__', `${options.devOptions.enabled ? options.devOptions.type : 'classic'}`) } export async function generateServiceWorker(options: ResolvedVitePWAOptions, viteOptions: ResolvedConfig): Promise { + if (options.selfDestroying) { + const selfDestroyingSW = ` +self.addEventListener('install', function(e) { + self.skipWaiting(); +}); +self.addEventListener('activate', function(e) { + self.registration.unregister() + .then(function() { + return self.clients.matchAll(); + }) + .then(function(clients) { + clients.forEach(client => client.navigate(client.url)) + }); +}); + ` + await fs.writeFile(options.swDest.replace(/\\/g, '/'), selfDestroyingSW, { encoding: 'utf8' }) + return { + count: 1, + size: selfDestroyingSW.length, + warnings: [], + filePaths: [options.filename], + } + } + const { generateSW } = loadWorkboxBuild() // generate the service worker @@ -39,6 +64,12 @@ export async function generateServiceWorker(options: ResolvedVitePWAOptions, vit } export async function generateInjectManifest(options: ResolvedVitePWAOptions, viteOptions: ResolvedConfig) { + const { selfDestroying } = options + if (selfDestroying) { + await generateServiceWorker(options, viteOptions) + return + } + // we will have something like this from swSrc: /* // sw.js diff --git a/src/options.ts b/src/options.ts index 175fc0ab..c0f04ea2 100644 --- a/src/options.ts +++ b/src/options.ts @@ -55,6 +55,7 @@ export async function resolveOptions(options: Partial, viteConfi useCredentials = false, disable = false, devOptions = { enabled: false, type: 'classic' }, + selfDestroying = false, } = options const basePath = resolveBathPath(base) @@ -148,6 +149,7 @@ export async function resolveOptions(options: Partial, viteConfi disable, devOptions, vitePlugins, + selfDestroying, } await configureStaticAssets(resolvedVitePWAOptions, viteConfig) diff --git a/src/plugins/dev.ts b/src/plugins/dev.ts index e24d9ff3..615b4a88 100644 --- a/src/plugins/dev.ts +++ b/src/plugins/dev.ts @@ -1,14 +1,21 @@ import { basename, resolve } from 'path' import { existsSync, promises as fs, mkdirSync } from 'fs' -import type { Plugin, ResolvedConfig } from 'vite' +import type { Plugin, ResolvedConfig, ViteDevServer } from 'vite' import { generateSimpleSWRegister, injectServiceWorker } from '../html' import { generateWebManifestFile } from '../assets' -import { DEV_SW_NAME, FILE_SW_REGISTER } from '../constants' +import { + DEV_SW_NAME, + FILE_SW_REGISTER, VIRTUAL_MODULES_RESOLVE_PREFIX, +} from '../constants' import type { ResolvedVitePWAOptions } from '../types' import { generateServiceWorker } from '../modules' import { normalizePath } from '../utils' import type { PWAPluginContext } from '../context' +const DEV_SW_VIRTUAL = `${VIRTUAL_MODULES_RESOLVE_PREFIX}pwa-entry-point-loaded` +const DEV_READY_NAME = 'vite-pwa-plugin:dev-ready' +const DEV_REGISTER_SW_NAME = 'vite-plugin-pwa:register-sw' + export const swDevOptions = { swUrl: DEV_SW_NAME, swDevGenerated: false, @@ -22,22 +29,22 @@ export function DevPlugin(ctx: PWAPluginContext): Plugin { transformIndexHtml: { enforce: 'post', async transform(html) { - const { options, useImportRegister, viteConfig } = ctx + const { options } = ctx if (options.disable || !options.manifest || !options.devOptions.enabled) return html - // if virtual register is requested, do not inject. - if (options.injectRegister === 'auto') - options.injectRegister = useImportRegister ? null : 'script' - - await createDevRegisterSW(options, viteConfig) + html = injectServiceWorker(html, options, true) - return injectServiceWorker(html, options, true) + return html.replace( + '', + ``, + ) }, }, configureServer(server) { const { options } = ctx if (!options.disable && options.manifest && options.devOptions.enabled) { + server.ws.on(DEV_READY_NAME, createSWResponseHandler(server, ctx)) const name = options.devOptions.webManifestUrl ?? `${options.base}${options.manifestFilename}` server.middlewares.use((req, res, next) => { if (req.url === name) { @@ -53,8 +60,11 @@ export function DevPlugin(ctx: PWAPluginContext): Plugin { } }, resolveId(id) { + if (id === DEV_SW_VIRTUAL) + return id + const { options } = ctx - if (!options.disable && options.devOptions.enabled && options.strategies === 'injectManifest') { + if (!options.disable && options.devOptions.enabled && options.strategies === 'injectManifest' && !options.selfDestroying) { const name = id.startsWith('/') ? id.slice(1) : id // the sw must be registered with .js extension on browser, here we detect that request: // - the .js file and source with .ts, or @@ -69,9 +79,12 @@ export function DevPlugin(ctx: PWAPluginContext): Plugin { return undefined }, async load(id) { + if (id === DEV_SW_VIRTUAL) + return generateSWHMR() + const { options, viteConfig } = ctx if (!options.disable && options.devOptions.enabled) { - if (options.strategies === 'injectManifest') { + if (options.strategies === 'injectManifest' && !options.selfDestroying) { // we need to inject self.__WB_MANIFEST with an empty array: there is no pwa on dev const swSrc = normalizePath(options.injectManifest.swSrc) if (id === swSrc) { @@ -93,6 +106,9 @@ export function DevPlugin(ctx: PWAPluginContext): Plugin { } if (id.endsWith(swDevOptions.swUrl)) { const globDirectory = resolve(viteConfig.root, 'dev-dist') + if (!existsSync(globDirectory)) + mkdirSync(globDirectory) + const swDest = resolve(globDirectory, 'sw.js') if (!swDevOptions.swDevGenerated || !existsSync(swDest)) { // we only need to generate sw on dev-dist folder and then read the content @@ -106,6 +122,7 @@ export function DevPlugin(ctx: PWAPluginContext): Plugin { {}, options, { + swDest: options.selfDestroying ? swDest : options.swDest, workbox: { ...options.workbox, navigateFallbackDenylist: [new RegExp(`^${webManifestUrl}$`)], @@ -154,3 +171,49 @@ async function createDevRegisterSW(options: ResolvedVitePWAOptions, viteConfig: } } +function createSWResponseHandler(server: ViteDevServer, ctx: PWAPluginContext): () => Promise { + return async () => { + const { options, useImportRegister } = ctx + const { injectRegister, scope, base } = options + // don't send the sw registration if virtual imported or disabled + if (!useImportRegister && injectRegister) { + if (injectRegister === 'auto') + options.injectRegister = 'script' + + await createDevRegisterSW(options, ctx.viteConfig) + + server.ws.send({ + type: 'custom', + event: DEV_REGISTER_SW_NAME, + data: { + inline: options.injectRegister === 'inline', + scope, + inlinePath: `${base}${DEV_SW_NAME}`, + registerPath: `${base}${FILE_SW_REGISTER}`, + }, + }) + } + } +} + +function generateSWHMR() { + return `import.meta.hot.on('${DEV_REGISTER_SW_NAME}', ({ inline, inlinePath, registerPath, scope }) => { + if (inline) { + if('serviceWorker' in navigator) { + navigator.serviceWorker.register(inlinePath, { scope }); + } + } + else { + const registerSW = document.createElement('script'); + registerSW.setAttribute('src', registerPath); + document.head.appendChild(registerSW); + } +}); + +try { + import.meta.hot.send('${DEV_READY_NAME}'); +} catch (e) { + console.error('unable to send ${DEV_READY_NAME} message to register service worker in dev mode!', e); +}` +} + diff --git a/src/plugins/main.ts b/src/plugins/main.ts index 0acb5ced..d27e485d 100644 --- a/src/plugins/main.ts +++ b/src/plugins/main.ts @@ -9,6 +9,7 @@ import { swDevOptions } from './dev' export function MainPlugin(ctx: PWAPluginContext): Plugin { return { name: 'vite-plugin-pwa', + enforce: 'pre', async configResolved(config) { ctx.useImportRegister = false ctx.viteConfig = config diff --git a/src/types.ts b/src/types.ts index 8a97394c..e241540b 100644 --- a/src/types.ts +++ b/src/types.ts @@ -130,6 +130,13 @@ export interface VitePWAOptions { * Development options. */ devOptions?: DevOptions + + /** + * Unregister the service worker? + * + * @default false + */ + selfDestroying?: boolean } export interface ResolvedVitePWAOptions extends Required {