window.location.reload with clear cache [duplicate] - javascript

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>

Related

Force hard reload in Nextjs [duplicate]

How can I force the web browser to do a hard refresh of the page via JavaScript?
Hard refresh means getting a fresh copy of the page AND refresh all the external resources (images, JavaScript, CSS, etc.).
⚠️ This solution won't work on all browsers. MDN page for location.reload():
Note: Firefox supports a non-standard forceGet boolean parameter for location.reload(), to tell Firefox to bypass its cache and force-reload the current document. However, in all other browsers, any parameter you specify in a location.reload() call will be ignored and have no effect of any kind.
Try:
location.reload(true);
When this method receives a true value as argument, it will cause the page to always be reloaded from the server. If it is false or not specified, the browser may reload the page from its cache.
More info:
The location object
window.location.href = window.location.href
Accepted answer above no longer does anything except just a normal reloading on mostly new version of web browsers today. I've tried on my recently updated Chrome all those, including location.reload(true), location.href = location.href, and <meta http-equiv="Cache-Control" content="no-cache, no-store, must-revalidate" />. None of them worked.
My solution is by using server-side capability to append non-repeating query string to all included source files reference as like below example.
<script src="script.js?t=<?=time();?>"></script>
So you also need to control it dynamically when to keep previous file and when to update it. The only issue is when files inclusion is performed via script by plugins you have no control to modify it. Don't worry about source files flooding. When older file is unlinked it will be automatically garbage collected.
Changing the current URL with a search parameter will cause browsers to pass that same parameter to the server, which in other words, forces a refresh.
(No guarantees if you use intercept with a Service Worker though.)
const url = new URL(window.location.href);
url.searchParams.set('reloadTime', Date.now().toString());
window.location.href = url.toString();
If you want support older browsers:
if ('URL' in window) {
const url = new URL(window.location.href);
url.searchParams.set('reloadTime', Date.now().toString());
window.location.href = url.toString();
} else {
window.location.href = window.location.origin
+ window.location.pathname
+ window.location.search
+ (window.location.search ? '&' : '?')
+ 'reloadTime='
+ Date.now().toString()
+ window.location.hash;
}
That said, forcing all your CSS and JS to refresh is a bit more laborious. You would want to do the same process of adding a searchParam for all the src attributes in <script> and href in <link>. That said it won't unload the current JS, but would work fine for CSS.
document.querySelectorAll('link').forEach((link) => link.href = addTimestamp(link.href));
I won't bother with a JS sample since it'll likely just cause problems.
You can save this hassle by adding a timestamp as a search param in your JS and CSS links when compiling the HTML.
This is a 2022 update with 2 methods, considering SPA's with # in url:
METHOD 1:
As mentioned in other answers one solution would be to put a random parameter to query string. In javascript it could be achieved with this:
function urlWithRndQueryParam(url, paramName) {
const ulrArr = url.split('#');
const urlQry = ulrArr[0].split('?');
const usp = new URLSearchParams(urlQry[1] || '');
usp.set(paramName || '_z', `${Date.now()}`);
urlQry[1] = usp.toString();
ulrArr[0] = urlQry.join('?');
return ulrArr.join('#');
}
function handleHardReload(url) {
window.location.href = urlWithRndQueryParam(url);
// This is to ensure reload with url's having '#'
window.location.reload();
}
handleHardReload(window.location.href);
The bad part is that it changes the current url and sometimes, in clean url's, it could seem little bit ugly for users.
METHOD 2:
Taking the idea from https://splunktool.com/force-a-reload-of-page-in-chrome-using-javascript-no-cache, the process could be to get the url without cache first and then reload the page:
async function handleHardReload(url) {
await fetch(url, {
headers: {
Pragma: 'no-cache',
Expires: '-1',
'Cache-Control': 'no-cache',
},
});
window.location.href = url;
// This is to ensure reload with url's having '#'
window.location.reload();
}
handleHardReload(window.location.href);
Could be even combined with method 1, but I think that with headers should be enought:
async function handleHardReload(url) {
const newUrl = urlWithRndQueryParam(url);
await fetch(newUrl, {
headers: {
Pragma: 'no-cache',
Expires: '-1',
'Cache-Control': 'no-cache',
},
});
window.location.href = url;
// This is to ensure reload with url's having '#'
window.location.reload();
}
handleHardReload(window.location.href);
UPDATED to refresh all the external resources (images, JavaScript, CSS, etc.)
Put this in file named HardRefresh.js:
function hardRefresh() {
const t = parseInt(Date.now() / 10000); //10s tics
const x = localStorage.getItem("t");
localStorage.setItem("t", t);
if (x != t) location.reload(true) //force page refresh from server
else { //refreshed from server within 10s
const a = document.querySelectorAll("a, link, script, img")
var n = a.length
while(n--) {
var tag = a[n]
var url = new URL(tag.href || tag.src);
url.searchParams.set('r', t.toString());
tag.href = url.toString(); //a, link, ...
tag.src = tag.href; //rerun script, refresh img
}
}
}
window.addEventListener("DOMContentLoaded", hardRefresh);
window.addEventListener("deviceorientation", hardRefresh, true);
This code do a fully controled forced hard refresh for every visitor, so that any update will show up without a cashing problem.
Duplicated DOM rendering is not a performance issue, because the first render is from cache and it stops rendering in <script src="js/HardRefresh.js"> where it reload a page from server. When it run a refreshed page it also refresh urls in page.
The last refresh time x is stored in localStorage. It is compared with the current time t to refresh within 10 seconds. Assuming a load from server not take more than 10 sec we manage to stop a page refresh loop, so do not have it less than 10s.
For a visitor of page the x != t is true since long time ago or first visit; that will get page from server. Then diff is less than 10s and x == t, that will make the else part add query strings to href and src having sources to refresh.
The refresh() function can be called by a button or other conditioned ways. Full control is managed by refining exclusion and inclusion of urls in your code.
For angular users and as found here, you can do the following:
<form [action]="myAppURL" method="POST" #refreshForm></form>
import { Component, OnInit, ViewChild } from '#angular/core';
#Component({
// ...
})
export class FooComponent {
#ViewChild('refreshForm', { static: false }) refreshForm;
forceReload() {
this.refreshForm.nativeElement.submit();
}
}
The reason why it worked was explained on this website: https://www.xspdf.com/resolution/52192666.html
You'll also find how the hard reload works for every framework and more in this article
explanation: Angular
Location: reload(), The Location.reload() method reloads the current URL, like the Refresh button. Using only location.reload(); is not a solution if you want to perform a force-reload (as done with e.g. Ctrl + F5) in order to reload all resources from the server and not from the browser cache. The solution to this issue is, to execute a POST request to the current location as this always makes the browser to reload everything.
The most reliable way I've found is to use a chache buster by adding a value to the querystring.
Here's a generic routine that I use:
function reloadUrl() {
// cache busting: Reliable but modifies URL
var queryParams = new URLSearchParams(window.location.search);
queryParams.set("lr", new Date().getTime());
var query = queryParams.toString();
window.location.search = query; // navigates
}
Calling this will produce something like this:
https://somesite.com/page?lr=1665958485293
after a reload.
This works to force reload every time, but the caveat is that the URL changes. In most applications this won't matter, but if the server relies on specific parameters this can cause potential side effects.

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 force the browser to reload a cached URL without changing the URL

An accident happened and a certain HTML page was set to be cached by browsers. We do not want to change the URL of that page because other parties rely on that URL (including SEO).
Is there a way to make as many clients as possible reload that page? Clients are often coming to that page when browsing around on the site so we are often able to send them some fresh JavaScript (or any other resource) before they hit the problematic page. Maybe there is a JavaScript trick to force a reload?!
Code snippet below will invalidate cache entry of the page with URI equal to uriOfCachedPage:
var xhr = new XMLHttpRequest();
xhr.open("GET", uriOfCachedPage, true);
xhr.setRequestHeader("Cache-Control", "max-age=0");
xhr.send();
You need to inject this code to script or HTML page that your users will probably get.
For more information check XMLHttpRequest page on MDN and Request Cache-Control Directives section in RFC 7232 Hypertext Transfer Protocol (HTTP/1.1): Caching.
You also can store cachedPageReloaded flag in cookies or localStorage and invalidate cache entry only if it wasn't invalidated before. Check Document.cookie and Window.localStorage pages on MDN.
Reload Page With TimeStamp Parameter Added to URL to Prevent Cached Versions From Being Loaded
Below is a function I use to reload an html page every time it is visited which appends a timestamp as a "version" parameter to the URL ensuring that it is never a cached copy of the page being retrieved.
// reloads page with a time-stamp appended to URL
// to ensure current form version loads
( function() {
var x = new Date().valueOf();
var now = x.toString().slice(-10);
var later = (x + 30000).toString().slice(-10);
var uSplit = window.location.href.toString().split('?');
if(uSplit.length > 1){
var oldNum = uSplit[1].slice(2);
var oldDate = parseInt(x.toString().replace(now, oldNum));
var diff = oldNum - now;
} else {
var diff = 0;
}
if(diff <= 0){
var newURL = uSplit[0] + "?v=" + later;
window.location.replace(newURL);
} else {
return false;
}
return false;
}());
This method adds a parameter to the URL, but it doesn't "change" it. It is the same method often used to carry over data from a form by adding the form data parameters to the end of the url.
Prevent Cached External .js Files
To ensure you are serving up-to-date javascript, that is included via script tags, from external .js files, you can use the jQuery getScript() function, which you can read about HERE. It adds a timestamp parameter to the end of the resource URL (not the actual page's URL), so that your external .js files being loaded are always current.
Example Usages:
$.getScript('url_to_your_javascript_file.js');
You can add timestamp as querystring at the end of your url:
var url = "http://yoursite.com/your.html?r=" + (new Date()).getTime();
You can invoke AJAX request with no cache option to not change the url and not refreshing the page either:
$.ajax({
url: "your.html",
cache: false, //<== don't cache!
type: "GET",
dataType: "json",
success: function(data, textStatus) {
$("#body").html(data);
}
});
Looking for a JavaScript solution?
window.location.reload(true);
Full HTML solution
<meta http-equiv="cache-control" content="max-age=0" />
<meta http-equiv="cache-control" content="no-cache" />
<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" />
Furher reading for adding these headers from server-side: https://stackoverflow.com/a/2068407/3958365

Chrome loading script twice when manually typing url to move to next page

I am having a bizarre issue that I'm thinking may be a Chrome bug or possibly a bug with Visual Studio. My script is getting loaded twice. To verify the issue I created a test script that sets a cookie with a timestamp to show the code is getting appended twice. If I navigate to the page via a hyperlink it works fine. Also if I hit the back and forth buttons it also works fine -- but if I manually type the url for the second page in the browser it calls the script twice.
This only happens in Chrome and only when using a Asp.Net Web Application. If I use a Asp.Net website, it does not occur. These are new empty web applications with no extra files or settings changed.
My example html pages look like this:
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>Page 1</title>
<script src="chromebug.js"></script>
</head>
<body>
<h1>Page 1</h1>
Page 1
Page 2
Page 3
</body>
</html>
And the chromebug.js look like this:
function getCookieTest(name) {
var cookie, cookies = document.cookie.split(';');
name = name + '=';
while ((cookie = cookies.pop())) {
cookie = cookie.replace(/^\s+/, '');
if (cookie.indexOf(name) === 0) {
return cookie.substring(name.length, cookie.length);
}
}
return null;
}
function setCookieTest(name, value, secs) {
var c;
if (secs > 0) {
c = new Date();
c.setSeconds(c.getSeconds() + secs);
c = name + '=' + value + '; expires=' + c.toGMTString() + '; path=/';
} else {
c = name + '=' + value + '; path=/';
}
document.cookie = c;
return
}
console.log('chromebug loaded');
var getdata = getCookieTest('loaded') || '';
setCookieTest('loaded', getdata.toString() + document.title + ':' + new Date().getTime().toString() + '|', 10000);
getdata = getCookieTest('loaded');
console.log(getdata); // show what has been saved in the cookie
Am I missing something? Any way to work around this?
I even created a video where the issue is demonstrated:
http://screencast.com/t/MpXfbDMBvfY
Thanks so much to stdob for pointing me to the Live HTTP Headers extension. I'd recommend it if you are having a similar issue.
https://chrome.google.com/webstore/detail/live-http-headers/iaiioopjkcekapmldfgbebdclcnpgnlo?hl=en
The issue in my case is with the Google Chrome prefetch optimization. When you type in the address bar, Google anticipates the page you will be loading and starts pulling down the scripts. If your script preforms some loading or cookie action upon loading this is problematic. When you uncheck this option you should see the duplicate loads go away.
However this is an easy way to control this without changing your settings. This is especially important since you have no control over your end-user's settings.
if (document.webkitVisibilityState && document.webkitVisibilityState == 'prerender') {
// avoid performing load logic
}
It's look like Chrome have non-obvious behavior when user manualy typing url in address bar. You can use some tools like Chrome live http headers to catch this behavior.

How can I force clients to refresh JavaScript files?

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

Categories