diff --git a/lib/app/SWUpdateEvent.js b/lib/app/SWUpdateEvent.js new file mode 100644 index 0000000000..7063ce96e2 --- /dev/null +++ b/lib/app/SWUpdateEvent.js @@ -0,0 +1,42 @@ +export default class SWUpdateEvent { + constructor (registration) { + Object.defineProperty(this, 'registration', { + value: registration, + configurable: true, + writable: true + }) + } + + /** + * Check if the new service worker exists or not. + */ + update () { + return this.registration.update() + } + + /** + * Activate new service worker to work 'location.reload()' with new data. + */ + skipWaiting () { + const worker = this.registration.waiting + if (!worker) { + return Promise.resolve() + } + + console.log('[vuepress:sw] Doing worker.skipWaiting().') + return new Promise((resolve, reject) => { + const channel = new MessageChannel() + + channel.port1.onmessage = (event) => { + console.log('[vuepress:sw] Done worker.skipWaiting().') + if (event.data.error) { + reject(event.data.error) + } else { + resolve(event.data) + } + } + + worker.postMessage({ type: 'skip-waiting' }, [channel.port2]) + }) + } +} diff --git a/lib/app/clientEntry.js b/lib/app/clientEntry.js index 4b11dbb48b..12eb56d8cd 100644 --- a/lib/app/clientEntry.js +++ b/lib/app/clientEntry.js @@ -1,6 +1,7 @@ /* global BASE_URL, GA_ID, ga, SW_ENABLED */ import { createApp } from './app' +import SWUpdateEvent from './SWUpdateEvent' import { register } from 'register-service-worker' const { app, router } = createApp() @@ -41,13 +42,13 @@ router.onReady(() => { console.log('[vuepress:sw] Service worker is active.') app.$refs.layout.$emit('sw-ready') }, - cached () { + cached (registration) { console.log('[vuepress:sw] Content has been cached for offline use.') - app.$refs.layout.$emit('sw-cached') + app.$refs.layout.$emit('sw-cached', new SWUpdateEvent(registration)) }, - updated () { + updated (registration) { console.log('[vuepress:sw] Content updated.') - app.$refs.layout.$emit('sw-updated') + app.$refs.layout.$emit('sw-updated', new SWUpdateEvent(registration)) }, offline () { console.log('[vuepress:sw] No internet connection found. App is running in offline mode.') diff --git a/lib/build.js b/lib/build.js index 9587da5542..cb37084bd3 100644 --- a/lib/build.js +++ b/lib/build.js @@ -81,11 +81,16 @@ module.exports = async function build (sourceDir, cliOptions = {}) { if (options.siteConfig.serviceWorker) { logger.wait('\nGenerating service worker...') const wbb = require('workbox-build') - wbb.generateSW({ + await wbb.generateSW({ swDest: path.resolve(outDir, 'service-worker.js'), globDirectory: outDir, globPatterns: ['**\/*.{js,css,html,png,jpg,jpeg,gif,svg,woff,woff2,eot,ttf,otf}'] }) + await fs.writeFile( + path.resolve(outDir, 'service-worker.js'), + await fs.readFile(path.resolve(__dirname, 'service-worker/skip-waiting.js'), 'utf8'), + { flag: 'a' } + ) } // DONE. diff --git a/lib/service-worker/skip-waiting.js b/lib/service-worker/skip-waiting.js new file mode 100644 index 0000000000..54fd8d37ce --- /dev/null +++ b/lib/service-worker/skip-waiting.js @@ -0,0 +1,12 @@ +addEventListener('message', event => { + const replyPort = event.ports[0] + const message = event.data + if (replyPort && message && message.type === 'skip-waiting') { + event.waitUntil( + self.skipWaiting().then( + () => replyPort.postMessage({ error: null }), + error => replyPort.postMessage({ error }) + ) + ) + } +}) diff --git a/package.json b/package.json index 728ee92581..da5649e4a3 100644 --- a/package.json +++ b/package.json @@ -75,7 +75,7 @@ "portfinder": "^1.0.13", "postcss-loader": "^2.1.5", "prismjs": "^1.13.0", - "register-service-worker": "^1.2.0", + "register-service-worker": "^1.3.0", "semver": "^5.5.0", "stylus": "^0.54.5", "stylus-loader": "^3.0.2", diff --git a/yarn.lock b/yarn.lock index 2dfaa93da1..b7e9af8a0e 100644 --- a/yarn.lock +++ b/yarn.lock @@ -7022,7 +7022,7 @@ regexpu-core@^4.1.3, regexpu-core@^4.1.4: unicode-match-property-ecmascript "^1.0.3" unicode-match-property-value-ecmascript "^1.0.1" -register-service-worker@^1.2.0: +register-service-worker@^1.3.0: version "1.3.0" resolved "https://registry.yarnpkg.com/register-service-worker/-/register-service-worker-1.3.0.tgz#02a0b7c40413b3c5ed1d801d764deb3aab1c3397"