Instantly update DOM when service worker detects a change - javascript

Is there any way to have service workers fetch the cached version, then attempt to do a network fetch, and if it's different than the cached version, put that new thing in the cache and replace the old asset in the DOM with the new one instantly (without having to refresh the page)?

Hey yeah this is a very tricky situation but what I did was save a version number to my .env file on production release.
I then built this NPM package which will surface the Version number of the .env at build time. I could then use this number in my VueJS - PWA to check against the old currently cached version number, and then do a network request if they dont match.
https://www.npmjs.com/package/vue-enverywhere

Related

How to purge browse cache - index.html stuck in cache

I have a ReactJS app hosted in S3 and using Cloudflare as DNS & CDN.
I have a huge issue, a lot of visitors have old version of the application stored in their browser cache (index.html only). I have configured advanced cache control in the newest version, but it cannot be accessed because older version is shown instead.
Static file (CSS, JS) versioning is done using create-react-app, but I have discovered that index.html file is the only cached one.
What should I do now?
How to purge visitors cache now?
PS: I have purged Cloudflare cache already and setup rule to bypass cache.
Unfortunately there is no such solution for this.
The only way is to wait until users cache will empty (expire).
It is technicaly impossible to clear users cache from external resource (JS script etc.), due to security reasons.
Also if it will be possible, there is no way how to tell users to download latest JS (including cache purging code), because they have old version of index.html (including link to those .js files).
You are stack and the only option is to wait.
A better approach would be, whenever your build changes, change the JS link so that the browser downloads the new version from the server, no matter the user's or the server's caching policy.
For example, the way Stack Exchange does it is, whenever the build changes, the HTML goes from something like:
<script src="https://cdn.sstatic.net/Js/stub.en.js?v=1bac371ac78f"></script>
to
<script src="https://cdn.sstatic.net/Js/stub.en.js?v=f83b2f654"></script>
Whenever there's a new build, you can randomize the parameter in the query string in the HTML, and still only have the single (most recent) built .js on your server.

Javascript clear browser cache for end user

Is there a way to clear browser cache using Javascript? When publishing a new release to an application, I sometimes have to tell my users to clear their browser cache to see the new changes.
The application is built using Vue.
I developed a PWA in Vue which had a lot of caching to be able to work offline as well, so distributing a new release was kind of tricky, solution that I settled on was deploying a version.txt file along my release and then periodically fetching that file from my app and when versions from .env files and version.txt don't match then I call:
caches.keys().then((keyList) => Promise.all(keyList.map((key) => caches.delete(key))));
to delete all cache, additionally I display a dialog that says new version is available and force a refresh so new content is served.
I hope this answer gives you an idea what you need to do to be able to publish a new version properly.

How to deal with webpack chunk updated on server?

We have a React application with code splitting using React.lazy and Suspend. Every Tuesday we deploy a new version and so our chunks will change too.
The problem we have right now is if our user did not refresh after we deploy, their old main.js is still pointing to the old chunk files with old hashes. And it's going to crash when they try to load the old chunk files.
We know that we can prefetch routes when our app is loaded but there are a lot of routes to be prefetched (around 20). This might affect our home page performance because we have a few API calls on home page.
Are there any better ways of dealing with this?
Many thanks in advance.
What keeps you from keeping multiple versions on your server? Let's say v1.commons.js is currently deployed. Now when you build a new version, v2.commons.js gets created, and both files are served by the server. Old clients will still work with the old version, but depending on your caching settings (page expiry time) they will migrate soon to the new version. Then you can remove the old version from your server.
Use the [hash] placeholder in the your Webpack output configuration, e.g. filename: '[hash]/[name].js'. This way every compilation will yield a fresh set of filenames.
Ensure the page that refers to these chunks (be it generated with webpack-html-plugin or something else) is always served fresh, never from cache, via Cache-Control headers or other similar techniques.
This way very stubborn clients (who disregard the cache-control headers) will most probably use their old version of your code, but as soon as they refresh (to get the new HTML page), they'll be guaranteed all of the new JavaScript too, since the URL has changed.
We have decided to preload every route in background so our clients do not need to lazy load other chunks at a later point in time.

Do scripts loaded with ocLazyLoad get cached by the browser?

Sorry if this is a newbish question.
I'm using the ocLazyLoad plugin with AngularJS and UI Router. I am using ocLazyLoad with Ui router to dynamically load/lazy-load in my controllers based on the route that is hit in my webapp.
My question is will these lazy-loaded scripts get cached by the browser? And if they are is there a way to force the browser to download a fresh copy (without turning off caching on my webserver).
The problem I am trying to solve is this, I wish to serve up a new version of my index.html with an MD5 hash to force browsers to reload code every time a new version of the webapp is deployed. So if I load up a new index-1ab34c.html my concern is that the lazy loaded JS files will be the same old cached ones and not the fresh code that is deployed.
This question asked more than 100 times actually by different type of question, angular router has a cache problem, the basic solution for this problem is version.
Desktop or laptop has a option to hard refresh ctrl + F5 this helps to reload all files from beginning, but devices like mobile or tablet doesn't have this option so you have to use version to handle this problem.
Try to version all of your requests and files, this helps
application to get new files and request by last version.
example:
var version = "0.0.1"; //0.0.2 // 0.0.9 // 0.1.0
//requests
$http.get("users?v=" + version).then(...);
//files
//loading with oclazyload or what you want no deference
"application/controller.js?v=" + version
Version is global variable because you will change it from one place every publish.

AngularJS app hot reload in production

I am using AngularJS 1.5.8 to build the client side of my webapp. I have frequent problems because users don't have the last version of the webapp client side. Is there an easy way to perform hot angular app reloading, in order my users to always have the last version? (I am looking for an alternative of websockets)
You can poll your server from your client web-app by using setInterval() with an ajax call to some REST endpoint that is capable of returning the most recent version. If that version doesn't match, say, your "version" variable, then you force a reload of the application.
In your index.html file where you load in all your .js files, you can include a version number in the URL that you increment whenever you do a new build. This will force the user's browser to reload the library from your server as the URL won't exactly match, effectively breaking the cache mechanism and preventing old versions of your code from loading.
The additional data in the URL won't have any effect on the application otherwise.
<script src="js/app.js?v1.2.3"></script>
<script src="js/services.js?v1.2.3"></script>
<script src="js/filters.js?v1.2.3"></script>
<script src="js/directives.js?v1.2.3"></script>
<script src="js/components.js?v1.2.3"></script>
You would do a search/replace for v1.2.3 to v1.2.4 on the next build.
If you're using something like webpack, or some other build pipeline / automation tool, you can do this automatically by including the hash of the library in the file name, and then dynamically updating the URL in the index.html file. When you see files like app.ad76c09743ef.js, that's likely how that's being generated. This ensures that even a single character change in your source results in a new, unique hash that will prevent the browser from using an older cached value.
The library I have used for this to good success is https://github.com/saintmac/angular-cache-buster
Each time the user makes a request for a resources, it will force latest version it not on white list.

Categories

Resources