Description:
We are using sw precache for caching the scripts before hand, hence to update the scripts we are giving reload option, for that we are listening the worker message to skip waiting the newly install service worker for unknown reason we are not getting correct
importScript
// GETTING OLD SW reference (self) and NOT getting newly installed SW reference
self.addEventListener('message', function(event) {
*// not working*
self.skipWaiting();
});
// But if we put skipWaiting() in 'install' listener
// it is getting correct new SW reference and working correctly
self.addEventListener('install', function(event) {
// self.skipWaiting();
});
SW registration
if('serviceWorker' in window.navigator) {
window.addEventListener('load', function() {
window.navigator.serviceWorker.register("/serviceWorker.js").then(function(registration) {
console.log("ServiceWorker registration successful with scope: ", registration);
registration.onupdatefound = function() {
console.log('NEW WILD WORKER HAS SPAWNED.!', registration);
var installedWorker = registration.installing;
installedWorker.onstatechange = function() {
if (installedWorker.state === 'installed') {
if (navigator.serviceWorker.controller) {
console.log('Updated content is available RELOAD!', navigator.serviceWorker.controller);
var el = document.getElementById('feature');
el.style['display'] = 'block';
}
}
}
}
}).catch(function(error) {
console.error("ServiceWorker registration failed: ", error);
});
});
window.navigator.serviceWorker.addEventListener('controllerchange', function() {
console.log('SERVICE WORKER UPDATED');
});
}
webpack config
new SWPrecacheWebpackPlugin({
cacheId: 'pwa',
filename: 'serviceWorker.js',
staticFileGlobsIgnorePatterns: [/\.map$/, /\.json$/, /_nch\.[0-9a-z]+\.[js, css]+/g, /webpackManifest\.[0-9a-z]+\.js/g, /.DS_Store\.[0-9a-z]+/g],
importScripts: ['offline/offline.1a2b3c4df1.js'],
dontCacheBustUrlsMatching: /./,
minify: false,
skipWaiting: false,
runtimeCaching: [ {
urlPattern: /_nch\.[0-9a-z]+\.[js, css]+/g,
handler: 'fastest',
options: {
cache: {
name: 'jd-internal-script',
maxEntries: 10,
},
},
}, {
urlPattern: /webpackManifest\.[0-9a-z]+\.js/g,
handler: 'networkFirst',
options: {
cache: {
name: 'jd-root-doc',
},
},
}],
}),
skipWaiting() method of the ServiceWorkerGlobalScope forces the waiting service worker to become the active service worker. Use this method with Clients. claim() to ensure that updates to the underlying service worker take effect immediately for both the current client and all other active clients.
Updating your service workerIt is only activated when there are no longer any pages loaded that are still using the old service worker. As soon as there are no more such pages still loaded, the new service worker activates. While this happens, the previous version is still responsible for fetches.
The best documentation for skipWaiting()
can be found at https://developers.google.com/web/fundamentals/instant-and-offline/service-worker/lifecycle#skip_the_waiting_phase
You can either call it unconditionally in the install
handler, or follow the model that you seem to be doing, which is to listen for a message
event and call skipWaiting()
conditionally.
If you go the conditional route, then you should modify your client page's code to properly detect when the service worker you're registering enters the waiting
state, and give the user the option of interacting with the page in a way that results in a corresponding postMessage()
to tell the service worker to skipWaiting()
. Based on what you're saying, you've tried this, but it looks like you're sending the message to the wrong service worker instance.
Here's what you page's code should look like:
// On your page:
if ('serviceWorker' in navigator) {
window.addEventListener('load', function() {
navigator.serviceWorker.register('service-worker.js').then(function(reg) {
reg.onupdatefound = function() {
var newSW = reg.installing;
newSW.onstatechange = function() {
if (newSW.state === 'waiting') {
// This assumes there's a button with id='skip-waiting-button' that
// users should click to get the new SW to activate immediately.
var button = document.querySelector('#skip-waiting-button');
button.addEventListener('click', function() {
newSW.postMessage('skipWaiting');
});
// Assume that 'display' is 'none' initially.
button.style.display = 'inline';
}
// Handle whatever other SW states you care about, like 'active'.
};
};
})
});
}
// In your service worker:
self.addEventListener('message', event => {
if (event.data === 'skipWaiting') {
self.skipWaiting();
}
});
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With