I'm trying to debug a issue about a PWA.
I use Google Chrome to daily run the webapp and also to debug this problem (both desktop and tablet).
When I edit service-worker.js (changing the cache storage name to get out an update), the webapp doesn't reload all files fetching them from the server, but a part of them are always cached, also if in Cache Storage the name of cache (only 1, so no multiple cache) is the right.
The same thing if I use different devices (Mac and Android tablet), so I believe is not a browser problem of a specific device. The strange thing is that if I use the "Clear site data" button to empty the cache, cookies, indexeddb, etc when I reload the page, the service-worker.js install the cache (with updated name) but if I go inside the detailed view there are some files with "Time Cached" too old, before I've cleared cache and site data.
For example, in the following picture you can see different time for some files. Consider that I used "Clear site data" button at 12/6/2020 19:17:50.
The following is the part of service-worker.js with "activate" event and the const with cache name.
const name_of_cache = ['cache_v1'];
self.addEventListener('activate', event => {
console.log('Service worker activate event!');
event.waitUntil(
caches.keys().then((cacheNames) => {
return Promise.all(
cacheNames.map((cacheKeyName) => {
if(name_of_cache.indexOf(cacheKeyName) === -1) {
return caches.delete(cacheKeyName);
}
}
));
})
);
});
Where am I doing wrong? How can I solve this issue, clearing the cache and all files every time I change service-worker.js and the name of the cache?
This answer is based in this Gist: https://gist.github.com/deanhume/4b7e1f136cbee288cff9f0fc46318fbb
if ('serviceWorker' in navigator) {
caches.keys().then(function(cacheNames) {
cacheNames.forEach(function(cacheName) {
caches.delete(cacheName);
});
});
}
This will loop through each cache you have and delete it.
Related
In a service-worker.js we can,
self.addEventListener("fetch", event => {
event.respondWith( caches.match(event.request).then(cachedResponse => { return cachedResponse || fetch(event.request); }) );
// See if the requested thing already exists in the cache and use it instead of re-downloading it.
// And only attempt to get a file from the remote server if it is not found within any of the caches.
});
Yes but, I'm wondering, in what case or cases would a browser not search through the caches first before trying to download a needed file? And therefore make this piece of code necessary?
Isn't it already the default thing that every browser does i.e. "Looking for the assets in the local system before trying to get them from far away"?
Is this perhaps only and only to try and keep the app/page going even if the internet connection is lost? Like prevent the browser from complaining even though the device has gone offline?
Any useful clarification is welcome and appreciated.
I made a sw.js file that caches my chat website so users can open in offline mode, however, the Service Worker file caused alot of issues including not being able to see new messages and alot of website crashes so I was forced to delete it. Sadly my none of my current users can delete the cache manually! NOte that I kept the sw.js file but it's now empty so is there any code I can write to delete all of my current user caches?
I don't think this is relevant but my app uses django
To delete the cache, you can use inbuild cache API.
caches.keys().then(cacheNames => {
cacheNames.forEach(value => {
caches.delete(value);
});
})
Removing content from your sw.js file is not enough. If there is already a service worker installed and running then I would suggest you to "unRegister" that also. You can do so
programmatically using below code.
navigator.serviceWorker.getRegistrations().then(function(registrations) {
for(let registration of registrations) {
registration.unregister()
}
})
Please note you only need to run this code once in all the user's browser.
I've completely rewritten a website, all it's resources have been moved to other folders (changed file structure) but if I access the site from a device that has cached it, it loads the old html file and looks for the old resource paths. I've tried to solve it with meta tags, I have changed the default index.php start file to home.php in .htaccess, I tried to solve it via js, but nothing works.
After days of searching, I think that I have found the problem. The webpage was transformed to a PWA and I registered a service worker for it to cache the index.php page. I think that this service worker's cache may be my problem. How can I update it in order to recache the website? The problem is, that I can update the index.php file however I want, the browser still loads the old file.
I am sure that it can be solved somehow, but I don't have any experiences with this. Any ideas? Thanks!
var cacheName = 'prisma-pwa';
var filesToCache = [
'/',
];
/* Start the service worker and cache all of the app's content */
self.addEventListener('install', function(e) {
e.waitUntil(
caches.open(cacheName).then(function(cache) {
return cache.addAll(filesToCache);
})
);
});
/* Serve cached content when offline */
self.addEventListener('fetch', function(e) {
e.respondWith(
caches.match(e.request).then(function(response) {
return response || fetch(e.request);
})
);
});
In some few cases it's not enough to reset with F5 or even CTRL-F5. Here helps to really delete the cache in your browser.
If you use Chrome than you can disable in preferences the cache while using DevTools. This helps me sometimes. The little loss of perfomance doesn't bother me for testing.
I'm new to Vue and created a project with the PWA Service-worker plugin. After deploying a new version of my App I get these messages in console:
After refreshing the page (F5) these messages still appear the same way and the App is still in it's old state. I tried everything to clear the cache but it still won't load the new content.
I haven't changed anything from the default config after creating my project and didn't add any code which interacts with the serviceworker. What is going wrong? Am I missing something?
As I figured out, this question is really only related to beginners in PWA, which don't know that you can (and need) to configure PWA for achieving this. If you feel addressed now (and using VueJS) remember:
To automatically download the new content, you need to configure PWA. In my case (VueJS) this is done by creating a file vue.config.js in the root directory of my project (On the same level as package.json).
Inside this file you need this:
module.exports = {
pwa: {
workboxOptions: {
skipWaiting: true
}
}
}
Which will automatically download your new content if detected.
However, the content won't be displayed to your client yet, since it needs to refresh after downloading the content. I did this by adding window.location.reload(true) to registerServiceWorker.js in my src/ directory:
updated () {
console.log('New content is available: Please refresh.')
window.location.reload(true)
},
Now, if the Service Worker detects new content, it will download it automatically and refresh the page afterwards.
I figured out a different approach to this and from what I've seen so far it works fine.
updated() {
console.log('New content is available; please refresh.');
caches.keys().then(function(names) {
for (let name of names) caches.delete(name);
});
},
What's happening here is that when the updated function gets called in the service worker it goes through and deletes all the caches. This means that your app will start up slower if there is an update but if not then it will serve the cached assets. I like this approach better because service workers can be complicated to understand and from what I've read using skipWaiting() isn't recommend unless you know what it does and the side effects it has. This also works with injectManifest mode which is how I'm currently using it.
pass registration argument then use the update() with that.
the argument uses ServiceWorkerRegistration API
updated (registration) {
console.log('New content is available; please refresh.')
registration.update()
},
I am developing a progressive web app and I had a problem with the service worker but under very specific conditions. I searched but no answer can solve my problem.
I saw the question Chrome install Service Worker addAll failed to fetch but I think that is not my problem because my SW fails to fetch only OGG files.
This is the event and problem:
The app cache png and ogg files.
Open with network access in desktop or Android mobile and both works very well, sounds and images.
Open offline in desktop and the same, sounds and images work well.
Open offline in mobile with Firefox, sounds and images work well.
Open offline in mobile with Chrome 67.0.3396.87 on Android or with Opera, or other webkit browser and images work well but sounds fail.
If I close and reopen the web immediately the cache store only the played sounds, only Chrome (or activate offline option in Network tab in the developer tools). That suggesting me that in Chrome the sounds only are cached after using them. But after a while, I reopen and happens the same as point 5. No sounds, perfect images, scripts and css.
I got the following errors and details:
Description in the console, using remote debugging
Network tab information for Chrome using remote debugging
This is my service worker (this is a new topic for me):
//13jul2018_8pm
var dataCacheName = 'name-pwa';
var cacheName = 'name-pwa';
var filesToCache = [
'/',
'manifest.json',
'index.html',
'main.js',
'img/img1.png',
'img/img2.png',
'img/spellHeal_8.png',
'img/heal.png',
'ogg/ogg1.ogg',
'ogg/ogg2.ogg',
'ogg/heal.ogg'
];
self.addEventListener('install', function(e) {
console.log('[ServiceWorker] Install');
e.waitUntil(
caches.open(cacheName).then(function(cache) {
console.log('[ServiceWorker] Caching app shell');
return cache.addAll(filesToCache);
})
);
});
self.addEventListener('activate', function(e) {
console.log('[ServiceWorker] Activate');
e.waitUntil(
caches.keys().then(function(keyList) {
return Promise.all(keyList.map(function(key) {
if (key !== cacheName && key !== dataCacheName) {
console.log('[ServiceWorker] Removing old cache', key);
return caches.delete(key);
}
}));
})
);
return self.clients.claim();
});
self.addEventListener('fetch', function(e) {
console.log('[Service Worker] Fetch', e.request.url);
e.respondWith(
caches.match(e.request).then(function(response) {
return response || fetch(e.request);
})
);
});
I tried to fix it changing the mode of using the ogg files:
a. In a <audio> element
b. Using Javascript injection with audio = new Audio
I change the entire SW with some prebuild to check if this is the problem, but it did not fix the problem.
Maybe someone has this problem and a way to solve it?
Thanks in advance, any suggestion is welcomed,
After trying many things I detected that Chrome, in both Android and Desktop is especially sensitive to lack of caching a promise problem, but this problem is only effective in my app when fetching a OGG (or other audio files) when offline. As posted in my question, PNG files work marvelously.
I solved finally the problem by modifying the fetch event of my service worker, including clone the request as suggested in Google help webpage. I am sharing the solution if someone has the same problem. Weird behavior in Google Chrome.
Here is the modified fetch event.
self.addEventListener('fetch', function(e) {
console.log('[Service Worker] Fetch', e.request.url);
e.respondWith(caches.match(e.request)
.then(function(response) {
return response || fetch(e.request)
.then(function (resp){
return caches.open(cacheName)
.then(function(cache){
cache.put(e.request, resp.clone());
return resp;
})
}).catch(function(event){
console.log('[Service Worker] Error fetching data!');
})
})
);
});