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
});
I have an AJAX-based application which consists of the following pages:
home.html --> browse_projects.html --> view_project.html
In home.html, I fetch a script as follows:
<head>
<script src="https://cdnjs.cloudflare.com/ajax/libs/materialize/0.97.8/js/materialize.min.js"></script>
</head>
After fetching materialize.min.js, I can see that the browser caches this.
Now, browse_projects.html also happens to require materialize.min.js.
So, I include it like this:
<script src="//cdnjs.cloudflare.com/ajax/libs/materialize/0.97.8/js/materialize.min.js"></script>
However, while running some tests, I notice that the browser does not retrieve it from the cache. Rather, it gets a new copy with an URL such as:
https://cdnjs.cloudflare.com/ajax/libs/materialize/0.97.8/js/materialize.min.js?_=1490644754909
Now, my question is - Why doesn't it retrieve the cached copy? How can I enforce this?
The reason it is not getting cached in your tests is this: _=1490644754909 - a random number is appended to the URL. Browsers cache static assets based upon the URL, if the URL changes every time, the browser will not cache the asset (aka: "cache busting"). If you are not using a templating library that can append the random string to the URL inline, you could load the scripts using Javascript instead:
<script>
function loadScript(src) {
var script = document.createElement('script');
script.src = script.src + '?_=' + (+new Date());
document.head.appendChild(script);
}
loadScript('https://cdnjs.cloudflare.com/ajax/libs/materialize/0.97.8/js/materialize.min.js');
</script>
This will append a random number to the end of your URL to prevent browser caching.
Lately I saw working code-blocks like this:
<script type="text/javascript" src="//ajax.googleapis.com/ajax/libs/jquery/1.3.2/jquery.min.js"></script>
And according to RFC 2396 (URI Syntax) and RFC 2616 (HTTP 1.1) these URI starting with two slashes are valid, but unfortunately the RFCs don't really explain them.
Can anyone point me to a resource which explains how browsers will/should/do process these URIs?
The resource you're looking for is the RFC 3986.
See Section 4.2 and Section 5.4. Quoting from the latter:
Reference Resolution Examples
Within a representation with a well defined base URI of:
http://a/b/c/d;p?q
a relative reference is transformed to its target URI as follows:
"g:h" = "g:h"
"g" = "http://a/b/c/g"
"./g" = "http://a/b/c/g"
"g/" = "http://a/b/c/g/"
"/g" = "http://a/g"
"//g" = "http://g"
"?y" = "http://a/b/c/d;p?y"
"g?y" = "http://a/b/c/g?y"
"#s" = "http://a/b/c/d;p?q#s"
"g#s" = "http://a/b/c/g#s"
"g?y#s" = "http://a/b/c/g?y#s"
";x" = "http://a/b/c/;x"
"g;x" = "http://a/b/c/g;x"
"g;x?y#s" = "http://a/b/c/g;x?y#s"
"" = "http://a/b/c/d;p?q"
"." = "http://a/b/c/"
"./" = "http://a/b/c/"
".." = "http://a/b/"
"../" = "http://a/b/"
"../g" = "http://a/b/g"
"../.." = "http://a/"
"../../" = "http://a/"
"../../g" = "http://a/g"
This means that when the base URI is http://a/b/c/d;p?q and you use //g, the relative reference is transformed to http://g.
These are protocol relative URLs. They point to an address, keeping the current protocol.
This notation is often used to avoid the "mixed content" problem (a IE warning message complaining about http and https resources on the same HTTPS page).
Update: Official documentation in RFC 3986:
A relative reference that begins with two slash characters is termed
a network-path reference; such references are rarely used. A
relative reference that begins with a single slash character is
termed an absolute-path reference. A relative reference that does
not begin with a slash character is termed a relative-path reference.
They are protocol independent urls. If the web page is served on https then the request uses https, if http then http.
The protocol-relative URL
Hidden features of HTML
Paul Irish seems to have popularized them by including it in his boilerplate code.
Be aware of that it is not only http or https independent, but also file, ftp, etc.
It means if you open .htm file directly in your browser on localhost, browser will resolve // as file protocol and your page won't work. It may cause problems in packed websites as "native" app using tools like Electron, PhoneGap, etc.
Example:
<script src="//mywebsite.com/resource.js"></script>
to
<script src="file://mywebsite.com/resource.js"></script>
I have a site http://www.example.com
I serve my static files from a different domain.
eg http://www.eg.com
in my js file which is located at http://www.eg.com/js/myscript.js
I have a variable which is an image.
var myvar = "images/example.gif";
I thought the image link would be http://www.eg.com/images/example.gif but it looks like (when I view the console) it grabs the domain name so it is getting http://www.example.com/images/example.gif
Is this expected behaviour?
Is there a way around this besides hardcoding the variable to be
var myvar = "http://www.eg.com/images/example.gif";
It's not ideal to hardcode as if the domain changes I will then need to update it twice?
It is the expected behavior because it's relative to the current URL.
If you need to use a different domain for your links/images then I would add a var to hold the host name and reference it in your JS file so you only have to change it in one place if you move the file.
So:
var domain = 'http://eg.com/';
var myvar = domain + "images/example.gif";
Or if you don't want to hardcode the domain, you could pull it from the JS source attribute:
HTML:
<script type="text/javascript" id="myjs" src="http://eg.com/myscript.js"></script>
Inside myscript.js:
var myjs = document.getElementById('myjs');
var domain = myjs.getAttribute('src').replace('myscript.js','');
var myvar = domain + "images/example.gif";
You could also just use the base tag in your header but there are some gotcha's.
All relative links are relative with respect to what you see in the address bar of the browser.
The only exception to this are images loaded in CSS (eg background-images), in which case paths are relative to the CSS file.
Edit: Though I haven't used it personally, W3C seems to define the base tag which could work for what you want
I'm trying to put a HTML code into a frame.
Out of frame I have used: document.write and into?
The frame is:
var frameTwitter = document.getElementById('FrameTwitter');
In order to write to an iFrame, you need to get its contentWindow or contentDocument.
var frameTwitter = document.getElementById('FrameTwitter'),
frameDocument = frameTwitter.contentWindow || frameTwitter.contentDocument;
frameDocument = frameDocument.document || frameDocument;
frameDocument.write('<p>Hello World!</p>');
DEMO: http://jsfiddle.net/NTICompass/8Ekrs/1/
UPDATE:
You can also use window.frames to get the iFrame's window object.
var frameDocument = window.frames.FrameTwitter.document;
frameDocument.write('<p>Hello World!</p>');
DEMO: http://jsfiddle.net/NTICompass/8Ekrs/2/
you have to use the postmessage API
see https://developer.mozilla.org/en-US/docs/DOM/window.postMessage
Rocket Hazmat is also correct
Normally, scripts on different pages are only allowed to access each other if and only if the pages which executed them are at locations with the same protocol (usually both http), port number (80 being the default for http), and host (modulo document.domain being set by both pages to the same value)
Since you're using 2 files that are on the same domain this should work. It's probably ideal to use a relative path on the iframe since you've got to match domains, protocols & ports or this will stop working.
MainPage.html
<iframe src="Frame.html" id="FrameTwitter"></iframe>
<script type="text/javascript">
var frame = document.getElementById('FrameTwitter');
frame.writeInto('Some text here');
</script>
Frame.html
<script type="text/javascript">
function writeInto(str) {
document.writeln(str);
}
</script>
That way you can set up the functionality you need for Frame.html within the file, test functionality there without worrying about cross-frame development yet. Then once your features are set up you can fire them from the parent.