I have a project created using Vue CLI 3 with Vue's PWA plugin included. I would like to display a banner prompting the user to click an in-app “Refresh” link as described here in the 'Approach #3' section.
But in my Vue.js app, because the service-worker code is executed in main.js
, and my snackbar banner is built into my App.vue
component, I'm not sure how to trigger my showRefreshUI()
method once the service-worker updated()
event has been called.
main.js
(applicable portion)
import Vue from 'vue';
import App from './App';
import './registerServiceWorker';
new Vue({
router,
render: h => h(App),
}).$mount('#app');
register-service-worker
(applicable portion)
import { register } from 'register-service-worker';
if (process.env.NODE_ENV === 'production') {
register(`${process.env.BASE_URL}service-worker.js`, {
updated (registration) {
console.log('New content is available; please refresh.');
// I'd like to call App.vue's showRefreshUI() method from here.
},
});
}
App.vue
(applicable portion)
<script>
export default {
name: 'App',
mounted () {
// Alternatively, I'd like to call this.showRefreshUI() from here
// when the service worker's updated() method is called.
},
methods: {
showRefreshUI () {
// My code to show the refresh UI banner/snackbar goes here.
},
},
};
</script>
If I can't call the showRefreshUI()
method from main.js
, how might I pass something from the updated()
event to App.vue
's mounted()
lifecycle hook to accomplish the same basic thing?
The final working solution for me was to leave main.js
untouched, and instead:
register-service-worker
(applicable portion)
import { register } from 'register-service-worker';
const UpdatedEvent = new CustomEvent('swUpdated', { detail: null });
if (process.env.NODE_ENV === 'production') {
register(`${process.env.BASE_URL}service-worker.js`, {
updated (registration) {
console.log('New content is available; please refresh.');
UpdatedEvent.detail = registration;
document.dispatchEvent(UpdatedEvent);
},
});
}
App.vue
(applicable portion)
<script>
export default {
name: 'App',
data () {
return {
registration: null,
};
},
mounted () {
document.addEventListener('swUpdated', this.showRefreshUI);
},
beforeDestroy () {
document.removeEventListener('swUpdated', this.showRefreshUI);
},
methods: {
showRefreshUI (e) {
this.registration = e.detail;
// My code to show the refresh UI banner/snackbar goes here.
},
},
};
</script>