I realize a similar Q was asked 5 years ago. I'm hoping there may be a better answer today.
Is there a programmatic way to tell a browser to expire its cached version of this page & to request a refresh from the server, next time? Time based expiry is not fast enough.
Requirement:
I want the client to constantly reload the the page from its own cache, until I tell it (via SignalR) that the page is obsolete. Then if I could flush just-that-page from the local cache, the next time the user looked at it, it would pull the latest version from the server. So once more it would be cached locally.
Why?
The data on the page takes a long time to download & the javascript adds seconds to the render time. Often it remains static for 30 mins or more. But occasionally it changes a few times a minute. So a fixed time interval cache, doesn't work.
ASP MVC lets me invalidate the Output cache of a page on the server. Which is great. If I could do the same on the client it would be an awesome speed improvement.
Note: I'm not changing the CSS, Images or Javascript. I just want strip out a lot of JScript & to do most of the HTML rendering on the server, once per data change event.
I had similar situation in my project where we wanted all clients to take latest version of files after each release. It was a simple spring MVC application. The fix we applied was we created a jsp tag which would add release number to all URL sent to server like:
www.abc.com/test.html/1
www.abc.com/test.html/2
Each time there is change in URL like this the browser does not uses cached copy but gets file from the server.
Release number you can keep in a config file and change after each release.
Related
I'm about to release a web application with a few pages. Each page is a Vue.js bundle. So on each page, there is a single javascript bundle & a single CSS file included, and a single div with a unique ID in the page where the app elements get mounted.
I need to be able to make updates to the static CSS/JS files without major service disruption. I'm using a Google Firebase backend for the application data, so if the client code doesn't update when an update is deployed, it could try to write to the database in the wrong format in an incorrect way. So, caching of the script files has been a problem.
I was initially under the impression that caches are invalidated when the hash of the file contents changes, but apparently that is not true. So, the core question is: How can I invalidate the browser cache of these files every time the content is updated?
What makes things complicated is that the web application may be embedded on clients' websites, by adding a small snippet to the page. And, I don't want to modify these snippets for every update - so I can't to change the filename with each version. E.g. in someoneswebsite.com.au/app/index.html:
<div id="my-app-mount"></div>
<script src="https://mywebapp.com.au/app/homepage.js"></script>
What won't work for me
Adding a query string or changing the filename with every update (Or other server-side tricks in PHP): I can't use any preprocessor as the snippet needs to be embeddable on other sites in HTML only.
Just setting a short TTL in the cache for these items. I need updates to work overnight, so I'd have to go down to just an hour or two. And this leads into the next point;
Disabling caching completely for these items: I don't want to flog my server with the extra traffic.
Just telling my users to do a hard-reload if they have any issues - this is a client-facing product.
My ideas for a solution so far
Change the filename with each upgrade app-1.0.js, app-1.1.js and so on, and add a 'bootstrap' script that gets the latest version based on a version string read from Firebase. However, this adds extra latency to every single page load as we need to hear from the database before loading the main JS payload.
In each javascript bundle, add a check to compare the app version with a version number retrieved from Firebase. If the script is out of date, we can programatically invalidate the cache and refresh the page (but how to do this?)
Some combination of HTTP cache headers, to always invalidate the cached copy if the hashed contents don't match the server.
I have a SPA Angular website. Whenever we release a change to the website, the user's browser does not go back to the server to get the new javascript files. The app happily keeps running in the user's browser, and while it will make ajax calls for data, the javascript files do not change. This can cause errors if the signature of the back-end API being called changes, etc. If the user refreshes the page, they get the updated javascript files and everything works fine after that.
Is there a way to tell the browser that the site has been updated and to get the new javascript files, rather than just running the app with the same files?
I use the Angular CLI to build the application, so when the website is released, the javascript files have hashes at the end etc. This isn't an issue with files being cached and not updated... it's an issue with the browser knowing that it needs to request the files or refresh the page.
You could use web workers to poll the server for changes and refresh the browser when changes are found.
An alternative to web workers is using setInteterval just refresh after a given time.
Yet another alternative is to have a version number in your API responses, and the JavaScript handlers would refresh the page when the version numbers are out of sync.
You could write a program in your angular code that:
periodically checks the version of the api if changes where made
does the periodic check to ascertain when the user is idle AND when the user is not in a edit page with dirty fields.
refreshes the page when step 2 condition is met
use this library to watch idleness
https://github.com/shawnmclean/Idle.js
If the file udated have the seame name add this text after the "?" like "?ver1.1" is suppose to tell the browser that there is a new version of the file.
you can use manifest file
https://html.spec.whatwg.org/multipage/offline.html#manifests
another way is with
CacheStorage,clear()
On cloudflare I want to disable caching and see my website changes immediately that I've pushed live.
Things I've tried:
I've put development mode on.
Create a bypass on caching in page rules.
Purged an individual webpage.
Purged the website.
Set cache to clear every 2 hours.
None of the above worked.
Tech I'm using:
Angular2
SystemJS
Typescript which becomes javascript on build.
Firebase for hosting and database.
Cloudflare for SSL etc.
The only way people see my website changes, it if they hard refresh.
The main problem is I've got a javascript file called app.js and its has all my javascript in for my Angular app. And it doesnt seem like its trying to get the resource in the browser.
I've changed the app.js to app.js?1490959855777
And still doesnt fetch the file again.
I basically want to see my JS file without a user having to hard refresh.
Based on the discussion above, it looks like the caching is happening on the browser - since a hard refresh will get the new file contents.
I think what happened is CF told the browser to hold onto that file for a very log time. And the browser is listening to that request.
Because you can't ask your users to do a hard refresh, you'll need to rename the static files that are being cached so aggressively.
This is not a programming question per se. I am using a free web host called getfreehosting. I am using their online file manager to transfer files. From time to time, the changes I make on source code do NOT reflect immediately after I upload them. I.e. when I run my application on Chrome, then go to view page source, I realize the JavaScript running is still the old version! In most cases this doesn't happen but when it does it is extremely frustrating. I've tried clearing the browser's cache. I even tried editing the file directly on their servers. Sometimes it solves the problem but other times it doesn't.
Is this a common issue encountered when transferring files to a web host? Or perhaps this is one of the downsides of using a free web host?
Thanks.
You can try clearing your browser's cache, or the ol' CTRL+F5 refresh trick. Otherwise, the hosting provider may be using a caching layer to help ease resource usage.
It is the responsibility of the server to indicate to the browser what the cacheable lifetime of the script files are when they are served to the browser (1 hr, 1 day, 1 month, etc...). This is a server side setting.
Caching is very important for both server-side efficiency and client-side performance so you don't want to defeat it completely.
You can either shorten the server-side setting for the cache lifetime or you can use a version number in your script files (like jQuery does) so that when you revise your script files, you give them a new filename like "myscript-v12.js" and update the corresponding HTML files to refer to the new filename. Then, as soon as the browser gets the new HTML file, it is guarenteed to get the new JS file because the new filename could never have been in the browser cache.
If this is just an issue for you personally while developing and revising your site, then just clear your browser cache after you upload new files and then when your browser loads that page, it won't have any version in the cache and will be forced to get the new version from the server.
There is a CACHE system in modern browsers.
Try clear cache before you browse your web site.
Following html5rocks' tutorial, I hoped that window.applicationCache.update() would help to force re-building the offline cache.
(http://www.html5rocks.com/en/tutorials/appcache/beginner/#toc-updating-cache)
The purpose is to allow the users to hit an "update cache" button. This, because even files (css, img, etc.) are modified, the computer/tablet doesn't even check them for udpates. The users are left with old content.
How can this be done in JS?
If you are asking "how the client should know that the files are modified", then the answer is simple - the cache manifest should contain some unique identifier which gets updated when those files are updated. I generate the manifest with PHP and use a combination of monotonous increasing revision number and MAX(filemtime) from all the cached files - when the manifest file is different from the one the client has, it will check all the manifest-listed files for updates.
update() triggers the update check and downloads the updates if there are any, but it doesn't actually replace old cached data with the new.
swapCache() will swap out the old cached version with a newly downloaded one.
However, at that point your old JS has already created all the plumbing your page depends on...
My html5 application calls update() periodically, and when the cache update is downloaded, it just displays a button to the user saying "Install Updates!", which simply reloads the page - that way the newly downloaded cache files are applied when the user chooses to, without breaking his workflow.