Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
94 changes: 94 additions & 0 deletions components/SWNewVersion.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
import { useEffect } from 'react'

export default function SWNewVersion () {
/*
* This hook only run once in browser after the component is rendered for the first time.
* It has same effect as the old componentDidMount lifecycle callback.
*/
useEffect(
() => {
if (typeof window !== 'undefined' && 'serviceWorker' in navigator && window.workbox !== undefined) {
const wb = window.workbox
/*
* Add event listeners to handle any of PWA lifecycle event
* https://developers.google.com/web/tools/workbox/reference-docs/latest/module-workbox-window.Workbox#events
*/
wb.addEventListener(
'installed',
(event) => {
console.log(`Event ${event.type} is triggered.`)
console.log(event)
}
)

wb.addEventListener(
'controlling',
(event) => {
console.log(`Event ${event.type} is triggered.`)
console.log(event)
}
)

wb.addEventListener(
'activated',
(event) => {
console.log(`Event ${event.type} is triggered.`)
console.log(event)
}
)

/*
* A common UX pattern for progressive web apps is to show a banner when a service worker has updated and waiting to install.
* NOTE: MUST set skipWaiting to false in next.config.js pwa object
* https://developers.google.com/web/tools/workbox/guides/advanced-recipes#offer_a_page_reload_for_users
*/
const promptNewVersionAvailable = (event) => {
/*
* `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 (confirm('A newer version of this web app is available, reload to update?')) {
wb.addEventListener(
'controlling',
(event) => {
window.location.reload()
}
)

// Send a message to the waiting service worker, instructing it to activate.
wb.messageSW({ type: 'SKIP_WAITING' })
} else {
console.log('User rejected to reload the web app, keep using old version. New version will be automatically loaded when user open the app next time.')
}
}

wb.addEventListener(
'waiting',
promptNewVersionAvailable
)
wb.addEventListener(
'externalwaiting',
promptNewVersionAvailable
)

/*
* ISSUE - this is not working as expected, why?
* I could only make message event listenser work when I manually add this listenser into sw.js file
*/
wb.addEventListener(
'message',
(event) => {
console.log(`Event ${event.type} is triggered.`)
console.log(event)
}
)

wb.register()
}
},
[]
)

return <p>peos</p>
}
6 changes: 4 additions & 2 deletions next.config.js
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
const withPWA = require('next-pwa')
const runtimeCaching = require('next-pwa/cache')
runtimeCaching[0].handler = 'StaleWhileRevalidate'

module.exports = withPWA({
pwa: {
register: true,
register: false,
dest: 'public',
runtimeCaching
runtimeCaching,
skipWaiting: false
},
crossOrigin: 'anonymous',
pageExtensions: [
Expand Down
2 changes: 2 additions & 0 deletions pages/_app.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import { StylesProvider } from '@material-ui/core/styles'
import { ThemeProvider } from 'components/ThemeContext'
import { version } from 'lib/version'
import { withRouter } from 'next/router'
import SWNewVersion from '../components/SWNewVersion'

class MyApp extends App {
constructor (props) {
Expand Down Expand Up @@ -69,6 +70,7 @@ class MyApp extends App {
<ThemeProvider>
<CssBaseline />
<Provider store={store}>
<SWNewVersion />
<NavBar title={this.state.title} />
<Box mt={2}>
<Component
Expand Down