Skip to content

Commit

Permalink
feat: load workbox window with dynamic import (#367)
Browse files Browse the repository at this point in the history
* feat: load workbox window with dynamic import

* chore: update

* chore: dynamic import when required

Co-authored-by: Anthony Fu <anthonyfu117@hotmail.com>
  • Loading branch information
userquin and antfu committed Sep 17, 2022
1 parent 3d1449a commit 6b17dfe
Showing 1 changed file with 54 additions and 44 deletions.
98 changes: 54 additions & 44 deletions src/client/build/register.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import { Workbox, messageSW } from 'workbox-window'
import type { RegisterSWOptions } from '../type'

// __SW_AUTO_UPDATE__ will be replaced by virtual module
Expand All @@ -24,10 +23,13 @@ export function registerSW(options: RegisterSWOptions = {}) {
onRegisterError,
} = options

let wb: Workbox | undefined
let wb: import('workbox-window').Workbox | undefined
let registration: ServiceWorkerRegistration | undefined
let registerPromise: Promise<void>
let sendSkipWaitingMessage: () => Promise<void> | undefined

const updateServiceWorker = async (reloadPage = true) => {
await registerPromise
if (!auto) {
// Assuming the user accepted the update, set up a listener
// that will reload the page as soon as the previously waiting
Expand All @@ -39,58 +41,66 @@ export function registerSW(options: RegisterSWOptions = {}) {
})
}

if (registration && registration.waiting) {
// Send a message to the waiting service worker,
// instructing it to activate.
// Note: for this to work, you have to add a message
// listener in your service worker. See below.
await messageSW(registration.waiting, { type: 'SKIP_WAITING' })
}
await sendSkipWaitingMessage?.()
}
}

if ('serviceWorker' in navigator) {
// __SW__, __SCOPE__ and __TYPE__ will be replaced by virtual module
wb = new Workbox('__SW__', { scope: '__SCOPE__', type: '__TYPE__' })
async function register() {
if ('serviceWorker' in navigator) {
const { Workbox, messageSW } = await import('workbox-window')
sendSkipWaitingMessage = async () => {
if (registration && registration.waiting) {
// Send a message to the waiting service worker,
// instructing it to activate.
// Note: for this to work, you have to add a message
// listener in your service worker. See below.
await messageSW(registration.waiting, { type: 'SKIP_WAITING' })
}
}
// __SW__, __SCOPE__ and __TYPE__ will be replaced by virtual module
wb = new Workbox('__SW__', { scope: '__SCOPE__', type: '__TYPE__' })

wb.addEventListener('activated', (event) => {
// this will only controls the offline request.
// event.isUpdate will be true if another version of the service
// worker was controlling the page when this version was registered.
if (event.isUpdate)
auto && window.location.reload()
else if (!autoDestroy)
onOfflineReady?.()
})
wb.addEventListener('activated', (event) => {
// this will only controls the offline request.
// event.isUpdate will be true if another version of the service
// worker was controlling the page when this version was registered.
if (event.isUpdate)
auto && window.location.reload()
else if (!autoDestroy)
onOfflineReady?.()
})

if (!auto) {
const showSkipWaitingPrompt = () => {
// \`event.wasWaitingBeforeRegister\` will be false if this is
// the first time the updated service worker is waiting.
// When \`event.wasWaitingBeforeRegister\` is true, a previously
// updated service worker is still waiting.
// You may want to customize the UI prompt accordingly.
if (!auto) {
const showSkipWaitingPrompt = () => {
// \`event.wasWaitingBeforeRegister\` will be false if this is
// the first time the updated service worker is waiting.
// When \`event.wasWaitingBeforeRegister\` is true, a previously
// updated service worker is still waiting.
// You may want to customize the UI prompt accordingly.

// Assumes your app has some sort of prompt UI element
// that a user can either accept or reject.
onNeedRefresh?.()
// Assumes your app has some sort of prompt UI element
// that a user can either accept or reject.
onNeedRefresh?.()
}

// Add an event listener to detect when the registered
// service worker has installed but is waiting to activate.
wb.addEventListener('waiting', showSkipWaitingPrompt)
// @ts-expect-error event listener provided by workbox-window
wb.addEventListener('externalwaiting', showSkipWaitingPrompt)
}

// Add an event listener to detect when the registered
// service worker has installed but is waiting to activate.
wb.addEventListener('waiting', showSkipWaitingPrompt)
// @ts-expect-error event listener provided by workbox-window
wb.addEventListener('externalwaiting', showSkipWaitingPrompt)
// register the service worker
wb.register({ immediate }).then((r) => {
registration = r
onRegistered?.(r)
}).catch((e) => {
onRegisterError?.(e)
})
}

// register the service worker
wb.register({ immediate }).then((r) => {
registration = r
onRegistered?.(r)
}).catch((e) => {
onRegisterError?.(e)
})
}

registerPromise = register()

return updateServiceWorker
}

0 comments on commit 6b17dfe

Please sign in to comment.