Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: load workbox window with dynamic import #367

Merged
merged 3 commits into from
Sep 17, 2022
Merged
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
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() {
const { Workbox, messageSW } = await import('workbox-window')
userquin marked this conversation as resolved.
Show resolved Hide resolved
if ('serviceWorker' in navigator) {
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
}