diff --git a/examples/vanilla-ts-dev-options/package.json b/examples/vanilla-ts-dev-options/package.json index 2b95fb5d..48383e8e 100644 --- a/examples/vanilla-ts-dev-options/package.json +++ b/examples/vanilla-ts-dev-options/package.json @@ -7,9 +7,11 @@ "dev-auto": "rimraf dev-dist && DEBUG=vite-plugin-pwa SW_DEV=true SW_INLINE=auto vite --force", "dev-inline": "rimraf dev-dist && DEBUG=vite-plugin-pwa SW_DEV=true SW_INLINE=inline vite --force", "dev-script": "rimraf dev-dist && DEBUG=vite-plugin-pwa SW_DEV=true SW_INLINE=script vite --force", + "dev-script-defer": "rimraf dev-dist && DEBUG=vite-plugin-pwa SW_DEV=true SW_INLINE=script-defer vite --force", "dev-auto-destroy": "rimraf dev-dist && DEBUG=vite-plugin-pwa SW_DEV=true SW_DESTROY=true SW_INLINE=auto vite --force", "dev-inline-destroy": "rimraf dev-dist && DEBUG=vite-plugin-pwa SW_DEV=true SW_DESTROY=true SW_INLINE=inline vite --force", "dev-script-destroy": "rimraf dev-dist && DEBUG=vite-plugin-pwa SW_DEV=true SW_DESTROY=true SW_INLINE=script vite --force", + "dev-script-defer-destroy": "rimraf dev-dist && DEBUG=vite-plugin-pwa SW_DEV=true SW_DESTROY=true SW_INLINE=script-defer vite --force", "build": "DEBUG=vite-plugin-pwa vite build", "build-auto": "rimraf dev-dist && DEBUG=vite-plugin-pwa SW_DEV=true SW_INLINE=auto vite build --force", "build-inline": "rimraf dev-dist && DEBUG=vite-plugin-pwa SW_DEV=true SW_INLINE=inline vite build --force", diff --git a/examples/vanilla-ts-dev-options/src/main.ts b/examples/vanilla-ts-dev-options/src/main.ts index 977322b6..74c4215b 100644 --- a/examples/vanilla-ts-dev-options/src/main.ts +++ b/examples/vanilla-ts-dev-options/src/main.ts @@ -7,6 +7,6 @@ document.querySelector('#app')!.innerHTML = `
PWA Logo

Vite + TypeScript

-

Testing SW with injectRegister=auto,inline,script

+

Testing SW with injectRegister=auto,inline,script,script-defer

` diff --git a/examples/vanilla-ts-dev-options/vite.config.ts b/examples/vanilla-ts-dev-options/vite.config.ts index 5a6080f7..1a449665 100644 --- a/examples/vanilla-ts-dev-options/vite.config.ts +++ b/examples/vanilla-ts-dev-options/vite.config.ts @@ -2,7 +2,7 @@ import process from 'node:process' import { defineConfig } from 'vite' import { VitePWA } from 'vite-plugin-pwa' -const injectRegister = (process.env.SW_INLINE ?? 'auto') as 'inline' | 'auto' | 'script' +const injectRegister = (process.env.SW_INLINE ?? 'auto') as 'inline' | 'auto' | 'script' | 'script-defer' const selfDestroying = process.env.SW_DESTROY === 'true' export default defineConfig({ diff --git a/info.d.ts b/info.d.ts index dd7eb61f..6d3e3d8b 100644 --- a/info.d.ts +++ b/info.d.ts @@ -16,7 +16,7 @@ declare module 'virtual:pwa-info' { } /** * The service worker data will be exposed only if required, that's, will **NOT** be exposed if: - * - not using `pwaPluginOptions.injectRegister` with `script` or `inline` values + * - not using `pwaPluginOptions.injectRegister` with `script`, `script-defer` or `inline` values * - if using `pwaPluginOptions.injectRegister` with `auto` (default) and importing any of the virtual modules */ registerSW?: { diff --git a/src/api.ts b/src/api.ts index 0e7aa5f9..32d3d8fb 100644 --- a/src/api.ts +++ b/src/api.ts @@ -42,7 +42,7 @@ export function _generateBundle({ options, viteConfig, useImportRegister }: PWAP if (options.injectRegister === 'auto') options.injectRegister = useImportRegister ? null : 'script' - if (options.injectRegister === 'script' && !existsSync(resolve(viteConfig.publicDir, FILE_SW_REGISTER))) { + if ((options.injectRegister === 'script' || options.injectRegister === 'script-defer') && !existsSync(resolve(viteConfig.publicDir, FILE_SW_REGISTER))) { bundle[FILE_SW_REGISTER] = { // @ts-expect-error: for Vite 3 support, Vite 4 has removed `isAsset` property isAsset: true, @@ -101,7 +101,7 @@ export function createAPI(ctx: PWAPluginContext): VitePluginPWAAPI { // 3: otherwise we always return the info let type: WorkerType = 'classic' let script: string | undefined - let shouldRegisterSW = options.injectRegister === 'inline' || options.injectRegister === 'script' + let shouldRegisterSW = options.injectRegister === 'inline' || options.injectRegister === 'script' || options.injectRegister === 'script-defer' if (ctx.devEnvironment && ctx.options.devOptions.enabled === true) { type = ctx.options.devOptions.type ?? 'classic' script = generateRegisterDevSW(ctx.options.base) diff --git a/src/html.ts b/src/html.ts index fca75ff6..507f0faa 100644 --- a/src/html.ts +++ b/src/html.ts @@ -32,7 +32,7 @@ export function injectServiceWorker(html: string, options: ResolvedVitePWAOption if (script) { return html.replace( '', - `${manifest}${script}`, + `${manifest}${script}`, ) } } @@ -57,8 +57,10 @@ export function generateWebManifest(options: ResolvedVitePWAOptions, dev: boolea export function generateRegisterSW(options: ResolvedVitePWAOptions, dev: boolean) { if (options.injectRegister === 'inline') return `` - else if (options.injectRegister === 'script') - return `` + else if (options.injectRegister === 'script' || options.injectRegister === 'script-defer') { + const hasDefer = options.injectRegister === 'script-defer' + return `` + } return undefined } @@ -72,9 +74,10 @@ registerDevSW(); } export function generateSWHMR() { + // defer attribute: https://html.spec.whatwg.org/multipage/common-microsyntaxes.html#boolean-attributes return ` -import.meta.hot.on('${DEV_REGISTER_SW_NAME}', ({ inline, inlinePath, registerPath, scope, swType = 'classic' }) => { - if (inline) { +import.meta.hot.on('${DEV_REGISTER_SW_NAME}', ({ mode, inlinePath, registerPath, scope, swType = 'classic' }) => { + if (mode == 'inline') { if('serviceWorker' in navigator) { navigator.serviceWorker.register(inlinePath, { scope, type: swType }); } @@ -82,6 +85,7 @@ import.meta.hot.on('${DEV_REGISTER_SW_NAME}', ({ inline, inlinePath, registerPat else { const registerSW = document.createElement('script'); registerSW.setAttribute('id', 'vite-plugin-pwa:register-sw'); + if (mode === 'script-defer') registerSW.setAttribute('defer', 'defer'); registerSW.setAttribute('src', registerPath); document.head.appendChild(registerSW); } diff --git a/src/plugins/dev.ts b/src/plugins/dev.ts index bae6dfaa..5eaab467 100644 --- a/src/plugins/dev.ts +++ b/src/plugins/dev.ts @@ -202,7 +202,7 @@ async function resolveDevDistFolder(options: ResolvedVitePWAOptions, viteConfig: } async function createDevRegisterSW(options: ResolvedVitePWAOptions, viteConfig: ResolvedConfig) { - if (options.injectRegister === 'script') { + if (options.injectRegister === 'script' || options.injectRegister === 'script-defer') { const devDist = await resolveDevDistFolder(options, viteConfig) if (!existsSync(devDist)) mkdirSync(devDist) @@ -236,7 +236,7 @@ function createSWResponseHandler(server: ViteDevServer, ctx: PWAPluginContext): type: 'custom', event: DEV_REGISTER_SW_NAME, data: { - inline: options.injectRegister === 'inline', + mode: options.injectRegister, scope, inlinePath: `${base}${DEV_SW_NAME}`, registerPath: `${base}${FILE_SW_REGISTER}`, diff --git a/src/types.ts b/src/types.ts index 295fc74e..609e8966 100644 --- a/src/types.ts +++ b/src/types.ts @@ -87,13 +87,15 @@ export interface VitePWAOptions { * * `inline` - inject a simple register, inlined with the generated html * - * `script` - inject