How can I force clients to refresh JavaScript files? - javascript

We are currently working in a private beta and so are still in the process of making fairly rapid changes, although obviously as usage is starting to ramp up, we will be slowing down this process. That being said, one issue we are running into is that after we push out an update with new JavaScript files, the client browsers still use the cached version of the file and they do not see the update. Obviously, on a support call, we can simply inform them to do a ctrlF5 refresh to ensure that they get the up-to-date files from the server, but it would be preferable to handle this before that time.
Our current thought is to simply attach a version number onto the name of the JavaScript files and then when changes are made, increment the version on the script and update all references. This definitely gets the job done, but updating the references on each release could get cumbersome.
As I'm sure we're not the first ones to deal with this, I figured I would throw it out to the community. How are you ensuring clients update their cache when you update your code? If you're using the method described above, are you using a process that simplifies the change?

As far as I know a common solution is to add a ?<version> to the script's src link.
For instance:
<script type="text/javascript" src="myfile.js?1500"></script>
I assume at this point that there isn't a better way than find-replace to increment these "version numbers" in all of the script tags?
You might have a version control system do that for you? Most version control systems have a way to automatically inject the revision number on check-in for instance.
It would look something like this:
<script type="text/javascript" src="myfile.js?$$REVISION$$"></script>
Of course, there are always better solutions like this one.

Appending the current time to the URL is indeed a common solution. However, you can also manage this at the web server level, if you want to. The server can be configured to send different HTTP headers for javascript files.
For example, to force the file to be cached for no longer than 1 day, you would send:
Cache-Control: max-age=86400, must-revalidate
For beta, if you want to force the user to always get the latest, you would use:
Cache-Control: no-cache, must-revalidate

Google Page-Speed: Don't include a query string in the URL for static resources.
Most proxies, most notably Squid up through version 3.0, do not cache resources with a "?" in their URL even if a Cache-control: public header is present in the response. To enable proxy caching for these resources, remove query strings from references to static resources, and instead encode the parameters into the file names themselves.
In this case, you can include the version into URL ex: http://abc.com/v1.2/script.js and use apache mod_rewrite to redirect the link to http://abc.com/script.js. When you change the version, client browser will update the new file.

How about adding the filesize as a load parameter?
<script type='text/javascript' src='path/to/file/mylibrary.js?filever=<?=filesize('path/to/file/mylibrary.js')?>'></script>
So every time you update the file the "filever" parameter changes.
How about when you update the file and your update results in the same file size? what are the odds?

This usage has been deprected:
https://developer.mozilla.org/en-US/docs/Web/HTML/Using_the_application_cache
This answer is only 6 years late, but I don't see this answer in many places... HTML5 has introduced Application Cache which is used to solve this problem. I was finding that new server code I was writing was crashing old javascript stored in people's browsers, so I wanted to find a way to expire their javascript. Use a manifest file that looks like this:
CACHE MANIFEST
# Aug 14, 2014
/mycode.js
NETWORK:
*
and generate this file with a new time stamp every time you want users to update their cache. As a side note, if you add this, the browser will not reload (even when a user refreshes the page) until the manifest tells it to.

Not all browsers cache files with '?' in it. What I did to make sure it was cached as much as possible, I included the version in the filename.
So instead of stuff.js?123, I did stuff_123.js
I used mod_redirect(I think) in apache to to have stuff_*.js to go stuff.js

The common practice nowadays is to generate a content hash code as part of the file name to force the browser especially IE to reload the javascript files or css files.
For example,
vendor.a7561fb0e9a071baadb9.js
main.b746e3eb72875af2caa9.js
It is generally the job for the build tools such as webpack. Here is more details if anyone wants to try out if you are using webpack.

For ASP.NET pages I am using the following
BEFORE
<script src="/Scripts/pages/common.js" type="text/javascript"></script>
AFTER (force reload)
<script src="/Scripts/pages/common.js?ver<%=DateTime.Now.Ticks.ToString()%>" type="text/javascript"></script>
Adding the DateTime.Now.Ticks works very well.

For ASP.NET I suppose next solution with advanced options (debug/release mode, versions):
Js or Css files included by such way:
<script type="text/javascript" src="Scripts/exampleScript<%=Global.JsPostfix%>" />
<link rel="stylesheet" type="text/css" href="Css/exampleCss<%=Global.CssPostfix%>" />
Global.JsPostfix and Global.CssPostfix is calculated by the following way in Global.asax:
protected void Application_Start(object sender, EventArgs e)
{
...
string jsVersion = ConfigurationManager.AppSettings["JsVersion"];
bool updateEveryAppStart = Convert.ToBoolean(ConfigurationManager.AppSettings["UpdateJsEveryAppStart"]);
int buildNumber = System.Reflection.Assembly.GetExecutingAssembly().GetName().Version.Revision;
JsPostfix = "";
#if !DEBUG
JsPostfix += ".min";
#endif
JsPostfix += ".js?" + jsVersion + "_" + buildNumber;
if (updateEveryAppStart)
{
Random rand = new Random();
JsPosfix += "_" + rand.Next();
}
...
}

If you're generating the page that links to the JS files a simple solution is appending the file's last modification timestamp to the generated links.
This is very similar to Huppie's answer, but works in version control systems without keyword substitution. It's also better than append the current time, since that would prevent caching even when the file didn't change at all.

In PHP:
function latest_version($file_name){
echo $file_name."?".filemtime($_SERVER['DOCUMENT_ROOT'] .$file_name);
}
In HTML:
<script type="text/javascript" src="<?php latest_version('/a-o/javascript/almanacka.js'); ?>">< /script>
How it works:
In HTML, write the filepath and name as you wold do, but in the function only.
PHP gets the filetime of the file and returns the filepath+name+"?"+time of latest change

We have been creating a SaaS for users and providing them a script to attach in their website page, and it was not possible to attach a version with the script as user will attach the script to their website for functionalities and i can't force them to change the version each time we update the script
So, we found a way to load the newer version of the script each time user calls the original script
the script link provided to user
<script src="https://thesaasdomain.com/somejsfile.js" data-ut="user_token"></script>
the script file
if($('script[src^="https://thesaasdomain.com/somejsfile.js?"]').length !== 0) {
init();
} else {
loadScript("https://thesaasdomain.com/somejsfile.js?" + guid());
}
var loadscript = function(scriptURL) {
var head = document.getElementsByTagName('head')[0];
var script = document.createElement('script');
script.type = 'text/javascript';
script.src = scriptURL;
head.appendChild(script);
}
var guid = function() {
return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) {
var r = Math.random() * 16 | 0, v = c == 'x' ? r : (r & 0x3 | 0x8);
return v.toString(16);
});
}
var init = function() {
// our main code
}
Explanation:
The user have attached the script provided to them in their website and we checked for the unique token attached with the script exists or not using jQuery selector and if not then load it dynamically with newer token (or version)
This is call the same script twice which could be a performance issue, but it really solves the problem of forcing the script to not load from the cache without putting the version in the actual script link given to the user or client
Disclaimer: Do not use if performance is a big issue in your case.

The jQuery function getScript can also be used to ensure that a js file is indeed loaded every time the page is loaded.
This is how I did it:
$(document).ready(function(){
$.getScript("../data/playlist.js", function(data, textStatus, jqxhr){
startProgram();
});
});
Check the function at http://api.jquery.com/jQuery.getScript/
By default, $.getScript() sets the cache setting to false. This appends a timestamped query parameter to the request URL to ensure that the browser downloads the script each time it is requested.

My colleague just found a reference to that method right after I posted (in reference to css) at http://www.stefanhayden.com/blog/2006/04/03/css-caching-hack/. Good to see that others are using it and it seems to work. I assume at this point that there isn't a better way than find-replace to increment these "version numbers" in all of the script tags?

In asp.net mvc you can use #DateTime.UtcNow.ToString() for js file version number. Version number auto change with date and you force clients browser to refresh automatically js file. I using this method and this is work well.
<script src="~/JsFilePath/JsFile.js?v=#DateTime.UtcNow.ToString()"></script>

One solution is to append a query string with a timestamp in it to the URL when fetching the resource. This takes advantage of the fact that a browser will not cache resources fetched from URLs with query strings in them.
You probably don't want the browser not to cache these resources at all though; it's more likely that you want them cached, but you want the browser to fetch a new version of the file when it is made available.
The most common solution seems to be to embed a timestamp or revision number in the file name itself. This is a little more work, because your code needs to be modified to request the correct files, but it means that, e.g. version 7 of your snazzy_javascript_file.js (i.e. snazzy_javascript_file_7.js) is cached on the browser until you release version 8, and then your code changes to fetch snazzy_javascript_file_8.js instead.

The advantage of using a file.js?V=1 over a fileV1.js is that you do not need to store multiple versions of the JavaScript files on the server.
The trouble I see with file.js?V=1 is that you may have dependant code in another JavaScript file that breaks when using the new version of the library utilities.
For the sake of backwards compatibility, I think it is much better to use jQuery.1.3.js for your new pages and let existing pages use jQuery.1.1.js, until you are ready to upgrade the older pages, if necessary.

Use a version GET variable to prevent browser caching.
Appending ?v=AUTO_INCREMENT_VERSION to the end of your url prevents browser caching - avoiding any and all cached scripts.

Cache Busting in ASP.NET Core via a tag helper will handle this for you and allow your browser to keep cached scripts/css until the file changes. Simply add the tag helper asp-append-version="true" to your script (js) or link (css) tag:
<link rel="stylesheet" href="~/css/site.min.css" asp-append-version="true"/>
Dave Paquette has a good example and explanation of cache busting here (bottom of page) Cache Busting

location.reload(true);
see https://www.w3schools.com/jsref/met_loc_reload.asp
I dynamically call this line of code in order to ensure that javascript has been re-retrieved from the web server instead of from the browser's cache in order to escape this problem.

Athough it is framework specific, Django 1.4 has the staticfiles app functionality which works in a similar fashion to the 'greenfelt' site in the above answer

One simple way.
Edit htaccess
RewriteEngine On
RewriteBase /
RewriteCond %{REQUEST_URI} \.(jpe?g|bmp|png|gif|css|js|mp3|ogg)$ [NC]
RewriteCond %{QUERY_STRING} !^(.+?&v33|)v=33[^&]*(?:&(.*)|)$ [NC]
RewriteRule ^ %{REQUEST_URI}?v=33 [R=301,L]

You can add file version to your file name so it will be like:
https://www.example.com/script_fv25.js
fv25 => file version nr. 25
And in your .htaccess put this block which will delete the version part from link:
RewriteEngine On
RewriteRule (.*)_fv\d+\.(js|css|txt|jpe?g|png|svg|ico|gif) $1.$2 [L]
so the final link will be:
https://www.example.com/script.js

FRONT-END OPTION
I made this code specifically for those who can't change any settings on the backend. In this case the best way to prevent a very long cache is with:
new Date().getTime()
However, for most programmers the cache can be a few minutes or hours so the simple code above ends up forcing all users to download "the each page browsed". To specify how long this item will remain without reloading I made this code and left several examples below:
// cache-expires-after.js v1
function cacheExpiresAfter(delay = 1, prefix = '', suffix = '') { // seconds
let now = new Date().getTime().toString();
now = now.substring(now.length - 11, 10); // remove decades and milliseconds
now = parseInt(now / delay).toString();
return prefix + now + suffix;
};
// examples (of the delay argument):
// the value changes every 1 second
var cache = cacheExpiresAfter(1);
// see the sync
setInterval(function(){
console.log(cacheExpiresAfter(1), new Date().getSeconds() + 's');
}, 1000);
// the value changes every 1 minute
var cache = cacheExpiresAfter(60);
// see the sync
setInterval(function(){
console.log(cacheExpiresAfter(60), new Date().getMinutes() + 'm:' + new Date().getSeconds() + 's');
}, 1000);
// the value changes every 5 minutes
var cache = cacheExpiresAfter(60 * 5); // OR 300
// the value changes every 1 hour
var cache = cacheExpiresAfter(60 * 60); // OR 3600
// the value changes every 3 hours
var cache = cacheExpiresAfter(60 * 60 * 3); // OR 10800
// the value changes every 1 day
var cache = cacheExpiresAfter(60 * 60 * 24); // OR 86400
// usage example:
let head = document.head || document.getElementsByTagName('head')[0];
let script = document.createElement('script');
script.setAttribute('src', '//unpkg.com/sweetalert#2.1.2/dist/sweetalert.min.js' + cacheExpiresAfter(60 * 5, '?'));
head.append(script);
// this works?
let waitSwal = setInterval(function() {
if (window.swal) {
clearInterval(waitSwal);
swal('Script successfully injected', script.outerHTML);
};
}, 100);

Simplest solution? Don't let the browser cache at all. Append the current time (in ms) as a query.
(You are still in beta, so you could make a reasonable case for not optimizing for performance. But YMMV here.)

Below worked for me:
<head>
<meta charset="UTF-8">
<meta http-equiv="cache-control" content="no-cache, must-revalidate, post-check=0, pre-check=0" />
<meta http-equiv="cache-control" content="max-age=0" />
<meta http-equiv="expires" content="0" />
<meta http-equiv="expires" content="Tue, 01 Jan 1980 1:00:00 GMT" />
<meta http-equiv="pragma" content="no-cache" />
</head>

If you are using PHP and Javascript then the following should work for you especially in the situation where you are doing multiple times changes on the file. So, every time you cannot change its version. So, the idea is to create a random number in PHP and then assign it as a version of the JS file.
$fileVersion = rand();
<script src="addNewStudent.js?v=<?php echo $fileVersion; ?>"></script>

<script>
var version = new Date().getTime();
var script = document.createElement("script");
script.src = "app.js?=" + version;
document.body.appendChild(script);
</script>
Feel free to delete this if someone's already posted it somewhere in the plethora of answers above.

You can do this with .htaccess
Add into your .htaccess file the following lines:
# DISABLE CACHING
<IfModule mod_headers.c>
<FilesMatch "\.js$">
Header set Cache-Control "no-store, max-age=0"
</FilesMatch>
</IfModule>

A simple trick that works fine for me to prevent conflicts between older and newer javascript files. That means: If there is a conflict and some error occurs, the user will be prompted to press Ctrl-F5.
At the top of the page add something like
<h1 id="welcome"> Welcome to this page <span style="color:red">... press Ctrl-F5</span></h1>
looking like
Let this line of javascript be the last to be executed when loading the page:
document.getElementById("welcome").innerHTML = "Welcome to this page"
In case that no error occurs the welcome greeting above will hardly be visible and almost immediately be replaced by

Related

does window.location.reload(true) clear cache of asynchronous loaded resources? [duplicate]

How do I clear a browsers cache with JavaScript?
We deployed the latest JavaScript code but we are unable to get the latest JavaScript code.
Editorial Note: This question is semi-duplicated in the following places, and the answer in the first of the following questions is probably the best. This accepted answer is no longer the ideal solution.
How to force browser to reload cached CSS/JS files?
How can I force clients to refresh JavaScript files?
Dynamically reload local Javascript source / json data
Update: See location.reload() has no parameter for background on this nonstandard parameter and how Firefox is likely the only modern browser with support.
You can call window.location.reload(true) to reload the current page. It will ignore any cached items and retrieve new copies of the page, css, images, JavaScript, etc from the server. This doesn't clear the whole cache, but has the effect of clearing the cache for the page you are on.
However, your best strategy is to version the path or filename as mentioned in various other answers. In addition, see Revving Filenames: don’t use querystring for reasons not to use ?v=n as your versioning scheme.
You can't clear the cache with javascript.
A common way is to append the revision number or last updated timestamp to the file, like this:
myscript.123.js
or
myscript.js?updated=1234567890
Try changing the JavaScript file's src? From this:
<script language="JavaScript" src="js/myscript.js"></script>
To this:
<script language="JavaScript" src="js/myscript.js?n=1"></script>
This method should force your browser to load a new copy of the JS file.
Other than caching every hour, or every week, you may cache according to file data.
Example (in PHP):
<script src="js/my_script.js?v=<?=md5_file('js/my_script.js')?>"></script>
or even use file modification time:
<script src="js/my_script.js?v=<?=filemtime('js/my_script.js')?>"></script>
You can also force the code to be reloaded every hour, like this, in PHP :
<?php
echo '<script language="JavaScript" src="js/myscript.js?token='.date('YmdH').'">';
?>
or
<script type="text/javascript" src="js/myscript.js?v=<?php echo date('YmdHis'); ?>"></script>
window.location.reload(true) seems to have been deprecated by the HTML5 standard. One way to do this without using query strings is to use the Clear-Site-Data header, which seems to being standardized.
put this at the end of your template :
var scripts = document.getElementsByTagName('script');
var torefreshs = ['myscript.js', 'myscript2.js'] ; // list of js to be refresh
var key = 1; // change this key every time you want force a refresh
for(var i=0;i<scripts.length;i++){
for(var j=0;j<torefreshs.length;j++){
if(scripts[i].src && (scripts[i].src.indexOf(torefreshs[j]) > -1)){
new_src = scripts[i].src.replace(torefreshs[j],torefreshs[j] + 'k=' + key );
scripts[i].src = new_src; // change src in order to refresh js
}
}
}
try using this
<script language="JavaScript" src="js/myscript.js"></script>
To this:
<script language="JavaScript" src="js/myscript.js?n=1"></script>
Here's a snippet of what I'm using for my latest project.
From the controller:
if ( IS_DEV ) {
$this->view->cacheBust = microtime(true);
} else {
$this->view->cacheBust = file_exists($versionFile)
// The version file exists, encode it
? urlencode( file_get_contents($versionFile) )
// Use today's year and week number to still have caching and busting
: date("YW");
}
From the view:
<script type="text/javascript" src="/javascript/somefile.js?v=<?= $this->cacheBust; ?>"></script>
<link rel="stylesheet" type="text/css" href="/css/layout.css?v=<?= $this->cacheBust; ?>">
Our publishing process generates a file with the revision number of the current build. This works by URL encoding that file and using that as a cache buster. As a fail-over, if that file doesn't exist, the year and week number are used so that caching still works, and it will be refreshed at least once a week.
Also, this provides cache busting for every page load while in the development environment so that developers don't have to worry with clearing the cache for any resources (javascript, css, ajax calls, etc).
or you can just read js file by server with file_get_contets and then put in echo in the header the js contents
Maybe "clearing cache" is not as easy as it should be. Instead of clearing cache on my browsers, I realized that "touching" the file will actually change the date of the source file cached on the server (Tested on Edge, Chrome and Firefox) and most browsers will automatically download the most current fresh copy of whats on your server (code, graphics any multimedia too). I suggest you just copy the most current scripts on the server and "do the touch thing" solution before your program runs, so it will change the date of all your problem files to a most current date and time, then it downloads a fresh copy to your browser:
<?php
touch('/www/control/file1.js');
touch('/www/control/file2.js');
touch('/www/control/file2.js');
?>
...the rest of your program...
It took me some time to resolve this issue (as many browsers act differently to different commands, but they all check time of files and compare to your downloaded copy in your browser, if different date and time, will do the refresh), If you can't go the supposed right way, there is always another usable and better solution to it. Best Regards and happy camping.
I had some troubles with the code suggested by yboussard. The inner j loop didn't work. Here is the modified code that I use with success.
function reloadScripts(toRefreshList/* list of js to be refresh */, key /* change this key every time you want force a refresh */) {
var scripts = document.getElementsByTagName('script');
for(var i = 0; i < scripts.length; i++) {
var aScript = scripts[i];
for(var j = 0; j < toRefreshList.length; j++) {
var toRefresh = toRefreshList[j];
if(aScript.src && (aScript.src.indexOf(toRefresh) > -1)) {
new_src = aScript.src.replace(toRefresh, toRefresh + '?k=' + key);
// console.log('Force refresh on cached script files. From: ' + aScript.src + ' to ' + new_src)
aScript.src = new_src;
}
}
}
}
If you are using php can do:
<script src="js/myscript.js?rev=<?php echo time();?>"
type="text/javascript"></script>
Please do not give incorrect information.
Cache api is a diferent type of cache from http cache
HTTP cache is fired when the server sends the correct headers, you can't access with javasvipt.
Cache api in the other hand is fired when you want, it is usefull when working with service worker so you can intersect request and answer it from this type of cache
see:ilustration 1 ilustration 2 course
You could use these techiques to have always a fresh content on your users:
Use location.reload(true) this does not work for me, so I wouldn't recomend it.
Use Cache api in order to save into the cache and intersect the
request with service worker, be carefull with this one because
if the server has sent the cache headers for the files you want
to refresh, the browser will answer from the HTTP cache first, and if it does not find it, then it will go to the network, so you could end up with and old file
Change the url from you stactics files, my recomendation is you should name it with the change of your files content, I use md5 and then convert it to string and url friendly, and the md5 will change with the content of the file, there you can freely send HTTP cache headers long enough
I would recomend the third one see
You can also disable browser caching with meta HTML tags just put html tags in the head section to avoid the web page to be cached while you are coding/testing and when you are done you can remove the meta tags.
(in the head section)
<meta http-equiv="Cache-Control" content="no-cache, no-store, must-revalidate" />
<meta http-equiv="Pragma" content="no-cache" />
<meta http-equiv="Expires" content="0"/>
Refresh your page after pasting this in the head and should refresh the new javascript code too.
This link will give you other options if you need them
http://cristian.sulea.net/blog/disable-browser-caching-with-meta-html-tags/
or you can just create a button like so
<button type="button" onclick="location.reload(true)">Refresh</button>
it refreshes and avoid caching but it will be there on your page till you finish testing, then you can take it off. Fist option is best I thing.
I tend to version my framework then apply the version number to script and style paths
<cfset fw.version = '001' />
<script src="/scripts/#fw.version#/foo.js"/>
Cache.delete() can be used for new chrome, firefox and opera.
I found a solution to this problem recently. In my case, I was trying to update an html element using javascript; I had been using XHR to update text based on data retrieved from a GET request. Although the XHR request happened frequently, the cached HTML data remained frustratingly the same.
Recently, I discovered a cache busting method in the fetch api. The fetch api replaces XHR, and it is super simple to use. Here's an example:
async function updateHTMLElement(t) {
let res = await fetch(url, {cache: "no-store"});
if(res.ok){
let myTxt = await res.text();
document.getElementById('myElement').innerHTML = myTxt;
}
}
Notice that {cache: "no-store"} argument? This causes the browser to bust the cache for that element, so that new data gets loaded properly. My goodness, this was a godsend for me. I hope this is helpful for you, too.
Tangentially, to bust the cache for an image that gets updated on the server side, but keeps the same src attribute, the simplest and oldest method is to simply use Date.now(), and append that number as a url variable to the src attribute for that image. This works reliably for images, but not for HTML elements. But between these two techniques, you can update any info you need to now :-)
Most of the right answers are already mentioned in this topic. However I want to add link to the one article which is the best one I was able to read.
https://www.fastly.com/blog/clearing-cache-browser
As far as I can see the most suitable solution is:
POST in an iframe. Next is a small subtract from the suggested post:
=============
const ifr = document.createElement('iframe');
ifr.name = ifr.id = 'ifr_'+Date.now();
document.body.appendChild(ifr);
const form = document.createElement('form');
form.method = "POST";
form.target = ifr.name;
form.action = ‘/thing/stuck/in/cache’;
document.body.appendChild(form);
form.submit();
There’s a few obvious side effects: this will create a browser history entry, and is subject to the same issues of non-caching of the response. But it escapes the preflight requirements that exist for fetch, and since it’s a navigation, browsers that split caches will be clearing the right one.
This one almost nails it. Firefox will hold on to the stuck object for cross-origin resources but only for subsequent fetches. Every browser will invalidate the navigation cache for the object, both for same and cross origin resources.
==============================
We tried many things but that one works pretty well. The only issue is there you need to be able to bring this script somehow to end user page so you are able to reset cache. We were lucky in our particular case.
window.parent.caches.delete("call")
close and open the browser after executing the code in console.
Cause browser cache same link, you should add a random number end of the url.
new Date().getTime() generate a different number.
Just add new Date().getTime() end of link as like
call
'https://stackoverflow.com/questions.php?' + new Date().getTime()
Output: https://stackoverflow.com/questions.php?1571737901173
I've solved this issue by using
ETag
Etags are similar to fingerprints, and if the resource at a given URL changes, a new Etag value must be generated. A comparison of them can determine whether two representations of a resource are the same.
Ref: https://developer.mozilla.org/en-US/docs/Web/API/Cache/delete
Cache.delete()
Method
Syntax:
cache.delete(request, {options}).then(function(found) {
// your cache entry has been deleted if found
});

How to prevent caching of spritesheet image, referenced in json?

I'm using PIXIJS engine and TexturePacker.
To prevent file caching I use:
<script type="text/javascript">
var PIXIJS_VERSION = "4.3.5";
var VERSION = "0.0.7b";
document.write('\<script src="lib/pixi.min.js?v=' + PIXIJS_VERSION + '">\<\/script>');
document.write('\<script src="game.js?v=' + VERSION + '">\<\/script>');
</script>
In my game.js I have:
PIXI.loader.add('images/textures.json?v=' + VERSION)
.add('images/fixedsys.xml?v=' + VERSION)
.load(setup);
So I just change the VERSION variable to force an update.
The problem is that textures.json is generated by TexturePacker, it contains:
"image": "textures.png"
And it's just inconvenient to add VERSION every time manually or even by a script:
"image": "textures.png?v=..."
PIXI.loader can only process json files or filenames, not objects, and I don't want to write complicated code for such a stupid case.
I also tried this to prevent caching at all:
<meta http-equiv="cache-control" content="no-cache, no-store, must-revalidate, post-check=0, pre-check=0">
And many other variations, that either didn't work in some cases.
So my question is why caching is so annoying and if there's a simple and elegant way to handle this problem?
This worked for me.
Before calling PIXI.loader.add, add the following middleware function:
// Append the version to each URL to bust the browser cache.
PIXI.loader.pre((resource, next) => { resource.url += `?v=${VERSION}`; next(); });
PIXI.loader.add('images/textures.json')
.add('images/fixedsys.xml')
.load(setup);
If you need to load files that have query string arguments you should improve the middleware function to parse the URL and append our extra argument properly. But this should do for your case.

IE taking script(dynamically added) from cache when added to onclick handler

[IE9] Consider the following code:
var scr = document.createElement("script");
scr.src = "http://collector.bonzai.mobi/expfreq?hours=1&freq=1&adid=abc&sn=source1&pub=publisher";
scr.onload = function(){
alert("openPage " + openPage);
}
document.body.appendChild(scr);
The problem is when I put this code directly in a <script> tag it works fine (means every time it contact server for retreiving the script). But if I keep the same code inside document.onclick function the IE9 is taking the script from cache 2nd time on wards. (I can see the 304 and <1ms)
PS : I cannot use Date.now() or any sort of cache bursting mechanism to append at the end of URL because the backend implementation depends of Cache (ETag).
Also I would suggest you clear your cache in IE browser before attempting each code change.
Any advice would be of great help. Thanks.
I got the solution for the problem. Setting "Cache-Control:private, must-revalidate" header from server solved the problem.
a solution from the client side could be :
scr.src = "http://collector.bonzai.mobi/expfreq?hours=1&freq=1&adid=abc&sn=source1&pub=publisher&timestamp=" + new Date().getTime();
So each request won't be cached.

How to append timestamp to the javascript file in <script> tag url to avoid caching

I want to append a random number or a timestamp at the end of the javascript file source path in so that every time the page reloads it should download a fresh copy.
it should be like
<script type="text/javascript" src="/js/1.js?v=1234455"/>
How can i generate and append this number? This is a simple HTML page, so cant use any PHP or JSP related code
Method 1
Lots of extensions can be added this way including Asynchronous inclusion and script deferring. Lots of ad networks and hi traffic sites use this approach.
<script type="text/javascript">
(function(){
var randomh=Math.random();
var e = document.getElementsByTagName("script")[0];
var d = document.createElement("script");
d.src = "//site.com/js.js?x="+randomh+"";
d.type = "text/javascript";
d.async = true;
d.defer = true;
e.parentNode.insertBefore(d,e);
})();
</script>
Method 2 (AJZane's comment)
Small and robust inclusion. You can see exactly where JavaScript is fired and it is less customisable (to the point) than Method 1.
<script>document.write("<script type='text/javascript' src='//site.com
/js.js?v=" + Date.now() + "'><\/script>");</script>
If you choose to use dates or a random numbers to append to your URI, you will provide opportunities for the end user to be served the same cached file and may potentially expose unintended security risks. An explicit versioning system would not. Here's why:
Why "Random" and Random Numbers are both BAD
For random numbers, you have no guarantee that same random number hasn't been generated and served to that user before. The likelihood of generating the same string is greater with smaller "random" number sets, or poor algorithms that provide the same results more often than others. In general, if you are relying on the JavaScript random method, keep in mind it's pseudo-random, and could have security implications as well if you are trying to rely on uniqueness for say a patch in one of your scripts for XSS vulnerabilities or something similar. We don't want Johnny to get served the old cached and unpatched JS file with an AJAX call to a no-longer trusted 3rd-party script the day Mr. Hacker happened to be visiting.
Why dates or timestamps are bad too, but not as bad
Regarding Dates as "unique" identifiers, JavaScript would be generating the Date object from the client's end. Depending on the date format, your chances for unintended caching may vary. Date alone (20160101) allows a full day's worth of potential caching issues because a visit in the morning results in foo.js?date=20160101, and so does a visit in the evening. Instead, if you specify down to the second (20160101000000) your odds of an end user calling the same GET parameter go down, but still exist.
A few rare but possible exceptions:
Clocks get reset (fall behind) once a year in most time zones
Computers that reset their local time on reboot for one reason or another
Automatic network time syncing causing your clock to adjust backwards a few seconds/minutes whenever your local time is off from the server time
Adjusting time zones settings when traveling (The astronauts on the IIS travel through a zone every few minutes...let's not degrade their browsing experience :P)
The user likes resetting their system clock to mess with you
Why incremental or unique versioning is good :)
For a fontend only solution, my suggestion would be to set an explicit version, which could be simply hard-coded by you or your team members every time you change the file. Manually doing exactly as you had done in your same code of your question would be a good practice.
You or your team should be the only ones editing your JS files, so the key take away isn't that your file needs to be served fresh every time, I just needs to be served fresh when it changes. Browser caching isn't a bad thing in your case, but you do need to tell the end user WHEN it should update. Essentially, when your file is updated, you want to ensure the client gets the updated copy. With this, you also have the added bonus of being able to revert to previous versions of your code without worry of client caching issues. The only drawback is you need to use due diligence to make sure you actually update the version number when you update your JS files. Keep in mind just because something isn't automated, doesn't mean it is necessarily bad practice or poor form. Make your solution work for your situation and the resources you have available.
I suggest using a form like Semantic Versioning's rules to easily identify backwards or breaking compatibility by looking at the file name (assuming nobody in the development process fudged up their version numbering) if possible. Unless you have an odd use case, there is no good reason to force a fresh copy down to the client every time.
Automated version incrementing on the client side with Local Storage
If what you were after was frontend way to automate the generation of a unique version number for you so you don't have to explicitly set it, then you would have to implement some sort of local storage method to keep track of, and auto increment your file versions. The solution I've shown below would lose the ability for Semantic versioning, and also has the potential to be reset if the user knows how to clear Local Storage. However, considering your options are limited to client-side only solutions, this may be your best bet:
<script type="text/javascript">
(function(){
/**
* Increment and return the local storage version for a given JavaScript file by name
* #param {string} scriptName Name of JavaScript file to be versioned (including .js file extension)
* #return {integer} New incremented version number of file to pass to .js GET parameter
*/
var incrementScriptVer = function(scriptName){
var version = parseInt(localStorage.getItem(scriptName));
// Simple validation that our item is an integer
if(version > 0){
version += 1;
} else {
// Default to 1
version = 1;
}
localStorage.setItem(scriptName, version);
return version;
};
// Set your scripts that you want to be versioned here
var scripts = ['foo.js', 'bar.js', 'baz.js'];
// Loop through each script name and append our new version number
scripts.map(function(script){
var currentScriptVer = incrementScriptVer(script);
document.write("<script language='text/javascript' type='text/javascript' src='http://yoursite.com/path/to/js/" + script + "?version=" + currentScriptVer + " '><\/script>");
});
})();
</script>
I'm going to mention for completeness, if you are converting from an old system of generating "random" numbered or dated GET variables, to an incrementing versioned system, be sure that you will not step over any potentially randomly generated files names with your new versioning system. If in doubt, add a prefix to your GET variable when changing methods, or simply add a new GET variable all together. Example: "foo.js?version=my_prefix_121216" or "foo.js?version=121216&version_system=incremental"
Automated versioning via AJAX calls and other methods (if backend development is a possiblity)
Personally, I like to stay away from local storage options. If the option is available, it would be the "best" solution. Try to get a backend developer make an endpoint to track JS file versions, you could always use the response to that endpoint determine your version number. If you are already using version control like Git, you could optionally have on of your Dev Ops team bind your versioning to your commit versions for some pretty sweet integration as well.
A jQuery solution to a RESTful GET endpoint might look like:
var script = "foo.js";
// Pretend this endpoint returns a valid JSON object with something like { "version": "1.12.20" }
$.ajax({
url: "//yoursite.com/path/to/your/file/version/endpoint/" + script
}).done(function(data) {
var currentScriptVer = data.version;
document.write("<script language='text/javascript' type='text/javascript' src='http://yoursite.com/path/to/js/" + script + "?version=" + currentScriptVer + " '><\/script>");
});
Insert the script dynamically via document.createElement('script'), then when you set the URL, you can use new Date().getTime() to append the extra parameter.
If you are worried about your javascript executing before the script is loaded, you can use the onload callback of the script element (note that there are a few hoops to jump for IE though)
If you can't user server side code then you can use getScript method to do the same.
$(document).ready(function(){
var randomNum = Math.ceil(Math.random() * 999999);
var jsfile = 'scripts/yourfile.js?v=' + randomNum;
$.getScript(jsfile, function(data, textStatus, jqxhr) { });
});
Reference URL: http://api.jquery.com/jQuery.getScript/
(Please don't forget to mark as answer.)
Load scripts manually or with jQuery http://api.jquery.com/jQuery.getScript/. It also provides option to prevent chaching
You can replace the source of the script doing this with pure Javascript
// get first script
var script = document.getElementsByTagName('script')[0]
var new = document.createElement("script");
// add the source with a timestamp
new.src = 'yoursource.js?' + new Date.getTime().toString();
new.type = 'text/javascript'
script.parentNode.insertBefore(new,script);
Replace regular expression if not alphanumeric
Date.prototype.toISOString()
var today = new Date();
"MyFile_" + today.toISOString().replace(/[^\w]/g, "") + ".pdf"
MyFile_20191021T173426146Z.pdf
Old post but here is a one liner:
<script src="../Scripts/source/yourjsname.js?ver<%=DateTime.Now.Ticks.ToString()%>" type="text/javascript"></script>

window.location.reload with clear cache [duplicate]

This question already has answers here:
JavaScript hard refresh of current page
(8 answers)
Closed 5 years ago.
I want to reload a page using JavaScript but I want to clear cache too, so on page refresh the page has latest versions of everything from server.
Other browsers except IE are not getting latest content.
Any solution for IE9?
reload() is supposed to accept an argument which tells it to do a hard reload, ie, ignoring the cache:
location.reload(true);
I can't vouch for its reliability, you may want to investigate this further.
Edit (2021): the parameter was never standardised and has been deprecated and removed in more modern browsers. Adding a comment every quarter describing this fact will not help.
You can do this a few ways. One, simply add this meta tag to your head:
<meta http-equiv="Cache-control" content="no-cache">
If you want to remove the document from cache, expires meta tag should work to delete it by setting its content attribute to -1 like so:
<meta http-equiv="Expires" content="-1">
http://www.metatags.org/meta_http_equiv_cache_control
Also, IE should give you the latest content for the main page. If you are having issues with external documents, like CSS and JS, add a dummy param at the end of your URLs with the current time in milliseconds so that it's never the same. This way IE, and other browsers, will always serve you the latest version. Here is an example:
<script src="mysite.com/js/myscript.js?12345">
UPDATE 1
After reading the comments I realize you wanted to programmatically erase the cache and not every time. What you could do is have a function in JS like:
eraseCache(){
window.location = window.location.href+'?eraseCache=true';
}
Then, in PHP let's say, you do something like this:
<head>
<?php
if (isset($_GET['eraseCache'])) {
echo '<meta http-equiv="Cache-control" content="no-cache">';
echo '<meta http-equiv="Expires" content="-1">';
$cache = '?' . time();
}
?>
<!-- ... other head HTML -->
<script src="mysite.com/js/script.js<?= $cache ?>"
</head>
This isn't tested, but should work. Basically, your JS function, if invoked, will reload the page, but adds a GET param to the end of the URL. Your site would then have some back-end code that looks for this param. If it exists, it adds the meta tags and a cache variable that contains a timestamp and appends it to the scripts and CSS that you are having caching issues with.
UPDATE 2
The meta tag indeed won't erase the cache on page load. So, technically you would need to run the eraseCache function in JS, once the page loads, you would need to load it again for the changes to take place. You should be able to fix this with your server side language. You could run the same eraseCache JS function, but instead of adding the meta tags, you need to add HTTP Cache headers:
<?php
header("Cache-Control: no-cache, must-revalidate");
header("Expires: Mon, 26 Jul 1997 05:00:00 GMT");
?>
<!-- Here you'd start your page... -->
This method works immediately without the need for page reload because it erases the cache before the page loads and also before anything is run.
i had this problem and i solved it using javascript
location.reload(true);
you may also use
window.history.forward(1);
to stop the browser back button after user logs out of the application.
In my case reload() doesn't work because the asp.net controls behavior. So, to solve this issue I've used this approach, despite seems a work around.
self.clear = function () {
//location.reload(true); Doesn't work to IE neither Firefox;
//also, hash tags must be removed or no postback will occur.
window.location.href = window.location.href.replace(/#.*$/, '');
};
I wrote this javascript script and included it in the header (before anything loads). It seems to work. If the page was loaded more than one hour ago or the situation is undefined it will reload everything from server.
The time of one hour = 3600000 milliseconds can be changed in the following line:
if(alter > 3600000)
With regards,
Birke
<script type="text/javascript">
//<![CDATA[
function zeit()
{
if(document.cookie)
{
a = document.cookie;
cookiewert = "";
while(a.length > 0)
{
cookiename = a.substring(0,a.indexOf('='));
if(cookiename == "zeitstempel")
{
cookiewert = a.substring(a.indexOf('=')+1,a.indexOf(';'));
break;
}
a = a.substring(a.indexOf(cookiewert)+cookiewert.length+1,a.length);
}
if(cookiewert.length > 0)
{
alter = new Date().getTime() - cookiewert;
if(alter > 3600000)
{
document.cookie = "zeitstempel=" + new Date().getTime() + ";";
location.reload(true);
}
else
{
return;
}
}
else
{
document.cookie = "zeitstempel=" + new Date().getTime() + ";";
location.reload(true);
}
}
else
{
document.cookie = "zeitstempel=" + new Date().getTime() + ";";
location.reload(true);
}
}
zeit();
//]]>
</script>

Categories