Skip to content

Commit

Permalink
feat: add 'script-defer' option for injectRegister script (#605)
Browse files Browse the repository at this point in the history
* feat: added 'script-defer' option to add defer attribute to service-worker loading script

* docs: revert changes

* docs: update jsdocs

* chore: change to `script-defer`

* chore: .

* chore: include logic for dev

* chore: include scripts for script-defer

---------

Co-authored-by: userquin <[email protected]>
  • Loading branch information
LouisMazel and userquin authored Nov 25, 2023
1 parent 7aca990 commit f183340
Show file tree
Hide file tree
Showing 8 changed files with 22 additions and 14 deletions.
2 changes: 2 additions & 0 deletions examples/vanilla-ts-dev-options/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand Down
2 changes: 1 addition & 1 deletion examples/vanilla-ts-dev-options/src/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,6 @@ document.querySelector<HTMLDivElement>('#app')!.innerHTML = `
<div>
<img src="/favicon.svg" alt="PWA Logo" width="60" height="60">
<h1>Vite + TypeScript</h1>
<p>Testing SW with <b>injectRegister=auto,inline,script</b></p>
<p>Testing SW with <b>injectRegister=auto,inline,script,script-defer</b></p>
</div>
`
2 changes: 1 addition & 1 deletion examples/vanilla-ts-dev-options/vite.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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({
Expand Down
2 changes: 1 addition & 1 deletion info.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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?: {
Expand Down
4 changes: 2 additions & 2 deletions src/api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -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)
Expand Down
14 changes: 9 additions & 5 deletions src/html.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ export function injectServiceWorker(html: string, options: ResolvedVitePWAOption
if (script) {
return html.replace(
'</head>',
`${manifest}${script}</head>`,
`${manifest}${script}</head>`,
)
}
}
Expand All @@ -57,8 +57,10 @@ export function generateWebManifest(options: ResolvedVitePWAOptions, dev: boolea
export function generateRegisterSW(options: ResolvedVitePWAOptions, dev: boolean) {
if (options.injectRegister === 'inline')
return `<script id="vite-plugin-pwa:inline-sw">${generateSimpleSWRegister(options, dev)}</script>`
else if (options.injectRegister === 'script')
return `<script id="vite-plugin-pwa:register-sw" src="${dev ? options.base : options.buildBase}${FILE_SW_REGISTER}"></script>`
else if (options.injectRegister === 'script' || options.injectRegister === 'script-defer') {
const hasDefer = options.injectRegister === 'script-defer'
return `<script id="vite-plugin-pwa:register-sw" src="${dev ? options.base : options.buildBase}${FILE_SW_REGISTER}" ${hasDefer ? 'defer' : ''}></script>`
}

return undefined
}
Expand All @@ -72,16 +74,18 @@ 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 });
}
}
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);
}
Expand Down
4 changes: 2 additions & 2 deletions src/plugins/dev.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down Expand Up @@ -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}`,
Expand Down
6 changes: 4 additions & 2 deletions src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -87,13 +87,15 @@ export interface VitePWAOptions {
*
* `inline` - inject a simple register, inlined with the generated html
*
* `script` - inject <script/> in <head>, with the `sr` to a generated simple register
* `script` - inject `<script/>` in `<head>` with `src` attribute to a generated script to register the service worker
*
* `script-defer` - inject `<script defer />` in `<head>`, with `src` attribute to a generated script to register the service worker
*
* `null` - do nothing, you will need to register the sw you self, or imports from `virtual:pwa-register`
*
* @default 'auto'
*/
injectRegister: 'inline' | 'script' | 'auto' | null | false
injectRegister: 'inline' | 'script' | 'script-defer' | 'auto' | null | false
/**
* Mode for the virtual register.
* Does NOT available for `injectRegister` set to `inline` or `script`
Expand Down

0 comments on commit f183340

Please sign in to comment.