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()
},
Related
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.
See the error on my website here
I have embedded a blazor app in my jekyll site. It runs perfectly locally, but when I publish it on github pages, I am getting this error:
Failed to find a valid digest in the 'integrity' attribute for resource 'https://chrisevans9629.github.io/blazor/xt/_framework/wasm/dotnet.3.2.0-rc1.20222.2.js' with computed SHA-256 integrity 'yVt8FYsTQDifOGsifIkmEXwe+7ML0jZ1dMi2xluiDXQ='. The resource has been blocked.
This is something that I think blazor generates when the page is ran. this is what my page looks like that starts blazor:
<script src="js/index.js"></script>
<app>Loading...</app>
Built with <3 using Blazor
<script src="_framework/blazor.webassembly.js"></script>
This is what the page looks like on github pages:
<script src="js/index.js"></script>
<app>Loading...</app>
<p>Built with <3 using Blazor
<script src="_framework/blazor.webassembly.js"></script></p>
<script type="text/javascript">var Module; window.__wasmmodulecallback__(); delete window.__wasmmodulecallback__;</script><script src="_framework/wasm/dotnet.3.2.0-rc1.20222.2.js" defer="" integrity="sha256-iZCHkFXJWYNxCUFwhj+4oqR4fkEJc5YGjfTTvdIuX84=" crossorigin="anonymous"></script></body>
Why is this error happening and how can I fix this? I've thought about create a script that would remove the integrity attribute, but I don't think that would be a good solution.
I found an answer here
Cause
Because I am using github pages to host my blazor app, it's using git to push up the code. Git by default will try to normalize line endings when committing code, which was causing the integrity of the blazor app to fail due to the files changing.
Solution
To fix this, I added a .gitattributes file to my blazor folder with * binary as the contents.
This tells git to treat all files as binary and therefore not to normalize the line endings. After I did that, I had to delete my _framework folder in my blazor app and rebuild it. After doing this, the blazor app worked.
In case someone else ends up here with the issue I had today..
I also got this error on a Blazor Wasm app locally after simple modification, and then still appeared after reverting changes.
The solution for me was to do a clean and rebuild.
In my case, it was a wrong target framework in the publish profile - I should not have selected win-x64.
I'm not sure of the exact reason, but the server interferes in some way with the response, based on the target framework. Just select browser-wasm and redeploy; it should be fine.
I spent too much time on this issue. Clean and Rebuild does not work for me.
What worked for me is deleting bin and obj folders from the Client(Blazor WASM) Project.
Environment
.Net 5 and 6
Visual Studio 2019 and 2022
Just to leave here a note on something I came across while trying to figure out what was going on.
If for some reason you removed the service worker from your app and the resources were actually cached in the common http cache, there is a possibility that once you re-enable the service worker you will get this error, because the service worker will pick up the http cached version and not the server's.
What I did was to add cache: "no-cache" to the Request's init.
So my onInstall now looks something like this
async function onInstall(event) {
console.info('Service worker: Install');
// Fetch and cache all matching items from the assets manifest
const assetsRequests = self.assetsManifest.assets
.filter(asset => offlineAssetsInclude.some(pattern => pattern.test(asset.url)))
.filter(asset => !offlineAssetsExclude.some(pattern => pattern.test(asset.url)))
.map(asset => new Request(asset.url, { integrity: asset.hash, cache: "no-cache" }));
// Also cache authentication configuration
assetsRequests.push(new Request('_configuration/TestApp.Client'));
await caches.open(cacheName).then(cache => cache.addAll(assetsRequests));
}
It looks like hash generated inside ServiceWorkerAssetsManifest for all the files and on the client side don't match. It looks like ServiceWorkerAssetsManifest is not generating hash again when the file is modified, specially the static files.
Had the same problem today, in my case the error came with a css file.
The problem was that I had two versions of my application deployed to local folders.
At first I started the old version, closed it and then opened up the new version.
It seems that the old css file was cached in the browser which caused the error to appear.
The fix was simply pressing CTRL + U to open up the index.html file, clicking on the css file which caused the error and press F5 to reload the file. This solved the error for me.
A better solution!
Open service-worker.js
change
.map(asset => new Request(asset.url, { integrity: asset.hash }));
to :
.map(asset => new Request(asset.url));
Now it works!
I Had this same issue and none of these solutions worked for me, but they set me on the right path. I am deploying mine to my local machine and using IIS for testing purposes, and I found that in the publish profile that I have created in Visual Studio 2022, the check box to "Remove additional files at destination" was not checked and as soon as I checked this and republished it, everything worked fine. I must have removed a file that was being published in a previous build and it was still there since it wasn't being deleted by any subsequent builds/publishes. But this solved it for me, it might
I have a React web application that allows Image uploads.
After performing a fetch POST request for multiple images (in this case 6) to my API, the browser refreshes itself and reloads the current page. It is worth noting that this application allows images to be cropped and so for every image the user uploads there is a second image (cropped) to upload. So the above 6 images result in 12 POST requests.
The refresh behavior is INCONSISTENT and difficult to reproduce. I have inserted breakpoints within the function this behavior occurs. Using the chrome debugger tools I have stepped through the flow and found that the refresh occurs after this call.
this.ws.onmessage = function(e) {
debug('message event', e.data);
self.emit('message', e.data);
};
It is located inside the file websocket.js within the Library node_modules/react-dev-tools/node_modules/socketjs-client/lib/transport/websocket.js
I have narrowed it down to this file and ruled out any issues from my project codebase.
My theory is that the behavior of my application is triggering an external listener/case which is causing a full browser refresh.
I see that the file in question is inside react-dev-tools and thought that removing this module could solve the problem, however, this occurs in my production environment also and so I feel removing this could break the build.
Any thoughts as to better my investigation or potential solutions please are helpful.
I'm not sure how you're running your environments, but maybe this will help...
I ran into this exact issue and it took me 3 days (too long) to narrow it to nodemon (in development) and pm2 (in production). I'm not sure how you're serving your application/images, but for me, any time a new file was added, the service was intermittently restarted (sometimes it uploaded, sometimes it was cut off).
For development, I added a nodemon.json config file at the application root (nodemon app.js --config nodemon.json):
{
"ignore": ["uploads"]
}
For production, I created a prod.json at the application root and ran pm2 start prod.json:
{
"apps" : [{
"name" : "app-name",
"ignore_watch" : ["uploads"],
"script" : "./app.js",
"env": {
"NODE_ENV": "production"
}
}]
}
If you're using neither of the above packages, then I'd suggest looking into the possibility of reconfiguring how you're storing and serving images to the application (as a last resort).
I'm using the react/react-router/webpack stack with dynamic routing between my different pages of the app which means every page loads asynchronously by demand. Everything works great but when I deploy a new version, my current active users who didn't fetch all of the Js file of all the pages will get stuck once the'll try to navigate to another page they haven't visited yet.
EXAMPLE
lets say I have a code split app with the following .js generated files and md5 (for cache busting):
main.123.js
profile.456.js
User visits my main page and gets only main.123.js.
In the meantime I deploy a new version with a different md5 (I made changes both in profile.js and main.js)
main.789.js
profile.891.js
User tries to navigate to the profile page, the app tries to fetch profile.456.js but get an error since the profile.js file has been swapped and there is now way for the app to know the new file name.
I came up with 2 solutions but none of them really solves the problem
SOLUTION 1?
Always keep 2 versions available in production. but it's a slippery slope since 2 versions sometimes won't be enough. i.e User can leave his tab open for days so several deployments can take place until he decides to use the app again.
SOLUTION 2?
catch the js loading exception and show the user a message to reload the app. This solution can work but it's an annoying UX if you ask me.
Has anyone experienced this kind of issue? Any suggestions?
EDIT - SOLUTION:
I have decided to go with the second approach (solution 2). In order to catch the loading error I had to upgrade my webpack to webpack 2 since require.ensure implementation doesn't support catching require file exception. With webpack 2 I can use System.import which supports error handling. So basically what I did is:
dynamic loading my component using System.import :
function getMyComponent(nextState, cb, path) {
return System.import('components/myComponent').then(module => {
cb(null, module);
});
}
And catching the error:
function getAsyncComponent(getComponent) {
return function (nextState, cb, path) {
getComponent(nextState, cb, path, store).catch(err => {
store.dispatch(notificationSend({message: <span>Uh oh.. Something went wrong.}));
cb(err);
});
}
}
<Route path="foo" getComponent={getAsyncComponent(getMyComponent)}/>
I would go for a variant of #2 where, upon detecting that a route file no longer exists on the server, you do a refresh for the user using window.location.reload(true). That should do a hard refresh which will load the new files.
I arrive to this problem quite a lot of times, where some of the users have a corrupt application cache (HTML 5).
I do update the manifest file every time there is a new release still some times some users get a corrupt application cache.
I such a case I want to fully clear what is there in their application cache and load all the fresh content from the server.
Is there a way to that using Javascript?
According to the following article on
http://www.w3schools.com/html5/html5_app_cache.asp
there are three ways on wich the application cache will be reset, these are:
The user clears the browser cache
The manifest file is modified
The application cache is programmatically updated
More information about programmatically updating the application cache can be found here:
http://www.html5rocks.com/en/tutorials/appcache/beginner/
It looks something like this:
var appCache = window.applicationCache;
appCache.update(); //this will attempt to update the users cache and changes the application cache status to 'UPDATEREADY'.
if (appCache.status == window.applicationCache.UPDATEREADY) {
appCache.swapCache(); //replaces the old cache with the new one.
}
This one is quite old but as I see a wrong answer being up-voted, I felt like giving some hint....
If ones has the trouble of looking at the spec, you can see that there's no way for code to force the browser to reload the cache, unless there's a change in the manifest, and that's when "appCache.status == window.applicationCache.UPDATEREADY" is true.
Look here http://www.w3.org/TR/2011/WD-html5-20110525/offline.html
"updateready The resources listed in the manifest have been newly redownloaded, and the script can use swapCache() to switch to the new cache."
So, reading it carefully, you find that the applicationCache gets to that status when the resources where just downloaded... that is.. a previous "downloading" event occurred... and previous to that one a "checking"....