Using JavaScript to invalidate the browser's cache - javascript

I'm doing a project in Django and using djangos-css (http://github.com/dziegler/django-css) and Sass (http://sass-lang.com/). The Sass files are served in development using django-css. I want to write a JavaScript routine that will every one second retrieve the CSS assets. The purpose of this is so that the designer can edit the Sass files, hit save, and see the result in the browser immediately without switching applications and hitting refresh.
Basically I need a way for JavaScript to force the browser to re-download certain files without doing a page refresh. Is this possible?

The simplest way is usually to add a unique parameter onto the url, I often just use a timestamp
var timestamp = (new Date()).getTime();
url += '?time=' + timestamp;
Just be careful if your requests already have parameters then you need to add &time=' + timstamp instead.
The browser can't cache the request because each request looks unique.

Not all caches will cache content with a query string.
Steve Souders recommends, “…avoiding a querystring for cacheable resources”. He found that in this case 5-20% of requests will not be cached. Query strings in particular do not work at all with some CDNs for cache invalidation.
The better way is to generate a MD5 with the javascript file name for each release e.g.
{path to script file}/filename-{md5 hash}.js

Related

How to clear browser cache using angularjs?

I just want to clear the browser cache using angularjs, every time i login to my application and browser should load new files.
You don't really do this using Angular, per se. There are a few ways you can cause your browser cache to invalidate/force your browser to request a fresh resource. A common way of doing this is cache busting your application assets. For example, whenever your JS changes, you have a task running (Grunt/Gulp/Webpack are good examples of this) that will rename your file to something new (usually by appending a hash or date to the end of the filename) so that when your browser requests your page, it will see a brand new filename and request a copy of it.
An example of something that can do this is gulp-rev: https://github.com/sindresorhus/gulp-rev and here is a tutorial: https://stefanimhoff.de/2014/gulp-tutorial-13-revisioning/
Hopefully this helps!
I recommand you to use grunt-cache-breaker is a simple cache-breaker, appends a timestamp or md5 hash to any url.
This plugin requires Grunt.

Loading a JS file from a CDN, how to prevent browser caching?

Every few hours (or less it depends) I will be updating a javascript file that will contain a JSON object that contains notifications that will appear on the website. This JSON object is what I will be updating periodically and so it cannot be cached by browsers.
The javascript will be hosted on a CDN, and this file will be on client websites like:
<script src="//example.com/1.7.1/my_file.js"></script>
How can I possible prevent browser caching in this type of situation?
I guess the best way would be for all clients to have the same javascript file, and then make an ajax request to pull down the messages? This way the "my_file.js" can be cached, but the ajax response will not be.
You can add a timestamp after the path my_file.js?time=currentTime
To keep the HTML clean you can add something like this in another local js file
$("head").append('<script type="text/javascript" src="yourPath?time=' + Date.now() + '"></script>');
Or you can use $.getScript, requirejs, etc.
It really depends on what CDN you use and the features available. Some approaches:
Instruct the CDN to cache the file for around an hour, so it'll automatically fetch a new one every hour (assuming someone is requesting). This means that users won't necessarily get the change immediately, but would be within half an hour of you changing
Along with that, Have the CDN send the end users a "no-cache" Cache-Control header. Depending on the CDN, this would simply be what your origin sends and you use some an override on the CDN (or one of the various means of instructing the CDN to cache it via headers, such as Surrogate-Cache-Control)
Alternatively, the above-mentioned versioning/timestamped URL. The downside of this is that it requires you to update any references to your file to include the version id. If your pages are auto-generated this is fine.
Allow the CDN to cache the file indefinitely, but make use of a "purge" or "invalidation" feature to force the CDN to request the new version the next time it is requested. This would mainly apply if you would have a reason to have the file not update for more than a few hours or a day.

getting related js files: What is the point of adding ?t=B48E5AB

I'm using CKEditor which is a multi-file library so the main js file calls other js and css files. I'm noticing that after the main file is called, additional files have a ?t=CODE added to them, so something like this, but the actual files don't have that extra ?t=B49E5BQ at the end.
http://site.com/ckeditor/config.js?t=B49E5BQ
http://site.com/ckeditor/extra.js?t=B49E5BQ
What's the point of this
P.S. Please feel free to add additional tags, because I'm not sure about this one.
This sort of trailing data is sometimes put into URLs for resources files like scripts/stylesheets so as to prevent caching of resources across re-deployments.
Whenever you change a resource, you change the code in HTML files/templates which require that resource, so that clients re-request the resource from the server the next time they load the page.
I would guess that the URL parameter is added to bypass any caching mechanisms. When a client sees the same URL with a different query parameter, that usually means the client can't use the cached version of the resource (in this case a JS file) and go to the server to fetch the latest version.
In HTTP, if a URL is the same in every way except for the URL parameters, a client can not assume that those files/resources are the same resulting object.
Which means:
http://site.com/ckeditor/config.js?t=B49E5BQ
is not the same as:
http://site.com/ckeditor/config.js?t=1234
It must be there to prevent caching.
I do this occasionally for images and script files. In my case, it's a meaningless argument (usually datetime) that just forces the browser to fetch a new copy every time.
If the parameter keeps changing, those files won't be cached on the client side.
Often this is easier than say, changing the name of the file to include a version number (jquery-1.6.2.js works nicely, but do you want to rename config.js to config-1.0.js, -2.0, etc. every time you make a change?
Like all the other answers, this simply forces the browser to grab the latest version when the querystring (?t=B49E5BQ) is changed. In our case, we simply add the date (?06022011).

Does Akamai pull from origin when query string parameters change for cached assets

So, I want to add versioning to my css and js files. The way I would like to do this is by appending a query string to the end of the asset path so
/foo/bar/baz.css
Becomes
/foo/bar/baz.css?version=1
This will work for proxies and browser cache, however, I was wondering if Akamai will know this is a new file and re-request it from the origin server? My assumption would be that it would re-request the file from the origin server but figured I'd ask if anyone knew for sure.
Yes. It matches exact URLs for all GET requests.
Not quite. It depends on the CDN configuration. Query String values are usually not part of the cache-key. So, when setting up the CDN delivery config, make sure you explicitly add the option to include the Query String as part of the cache-key. Otherwise, you will end up serving inconsistent versions due to having a cache key that does not vary based on the query string value, in this case, the asset version.
I prefer to have a url like '/css/DEVELOPER_BASE/foo/baz/style.css'.
Your build/deploy scripts do a global find and replace on '/css/DEVELOPER_BASE/' with '/css/[version_number]/'
To make this work you then have two options.
Your deploy script copies the css files from '/css/DEVELOPER_BASE/' to '/css/[version_number]/'
Your web server does an alias (not redirect) for '/css/[version_number]/' to '/css/DEVELOPER_BASE/'
This will keep you from having to worry about how browsers and CDN's handle query parameters.

Why pass parameters to CSS and JavaScript link files like src="../cnt.js?ver=4.0"?

When I saw many sites' source code, parameters were passed to the linking file (CSS/JavaScript).
In the Stack Overflow source, I got
<script type="text/javascript" src="http://sstatic.net/js/master.js?v=55c7eccb8e19"></script>
Why is master.js?v=55c7eccb8e19 used?
I am sure that JavaScript/CSS files can't get the parameters.
What is the reason?
It is usually done to prevent caching.
Let's say you deploy version 2 of your new application and you want to cause the clients to refresh their CSS, you could add this extra parameter to indicate that it should re-request it from the server. Of course there are other approaches as well, but this is pretty simple.
As the others have said, it's probably an attempt to control caching, although I think it's best to do so by changing the actual resource name (foo.v2.js, not foo.js?v=2) rather than a version in the query string. (That doesn't mean you have to rename files, there are better ways of mapping that URL to the underlying file.) This article, though four years old and therefore ancient in the web world, is still a quite useful discussion. In it, the author claims that you don't want to use query strings for versions because:
...According the letter of the HTTP caching specification, user agents should never cache URLs with query strings. While Internet Explorer and Firefox ignore this, Opera and Safari don’t...
That statement may not be quite correct, because what the spec actually says is
...since some applications have traditionally used GETs and HEADs with query URLs (those containing a "?" in the rel_path part) to perform operations with significant side effects, caches MUST NOT treat responses to such URIs as fresh unless the server provides an explicit expiration time...
(That emphasis at the end is mine.) So using a version in the query string may be fine as long as you're also including explicit caching headers. Provided browsers implement the above correctly. And proxies do. You see why I think you're better off with versions in the actual resource locator, rather than query parameters (which [again] doesn't mean you have to constantly rename files; see the article linked above for more). You know browsers, proxies, etc. along the way are going to fetch the updated resource if you change its name, which means you can give the previous "name" a never-ending cache time to maximize the benefit of intermediate caches.
Regarding:
I am sure that Js/CSS files can't get the parameters.
Just because the result coming back is a JavaScript or CSS resource, it doesn't mean that it's a literal file on the server's file system. The server could well be doing processing based on the query string parameters and generating a customized JavaScript or CSS response. There's no reason I can't configure my server to route all .js files to (say) a PHP handler that looks at the query string and returns something customized to match the fields given. Thus, foo.js?v=2 may well be different from foo.js?v=1 if I've set up my server to do so.
That's to avoid the browser from caching the file. The appending version name has no effect on the JavaScript file, but to the browser's caching engine it looks like a unique file now.
For example, if you had scripts.js and the browser visits the page, they download and cache (store) that file to make the next page visit faster. However, if you make a change the browser may not recognize it until the cache has expired. However, scripts.js?v2 now makes the browser force a re-fetch because the "name's changed" (even though it hasn't, just the contents have).
A server-side script generating the CSS or JavaScript code could make use of them, but it is probably just being used to change the URI when the the content of the file changes so that old, cached versions won't cause problems.
<script type="text/javascript">
// front end cache bust
var cacheBust = ['js/StrUtil.js', 'js/protos.common.js', 'js/conf.js', 'bootstrap_ECP/js/init.js'];
for (i=0;i<cacheBust.length;i++){
var el = document.createElement('script');
el.src = cacheBust[i]+"?v=" + Math.random();
document.getElementsByTagName('head')[0].appendChild(el);
}
</script>
This is to force the browser to re-cache the .js file if there has been any update.
You see, when you update your JS on a site, some browsers may have cached the old version (to improve performace). Sicne you want them to use your new one, you can append something in the query-field of the name, and voíla! The browser re-fetches the file!
This applies to all files sent from the server btw.
Since javascript and css files are cached by the client browser, so we append some numeric values against their names in order to provide the non-cached version of the file
"I am sure that JavaScript /CSS files can't get the parameters"
function getQueryParams(qs) {
qs = qs.split("+").join(" ");
var params = {},
tokens, re = /[?&]?([^=]+)=([^&]*)/g;
while (tokens = re.exec(qs)) {
params[decodeURIComponent(tokens[1])] = decodeURIComponent(tokens[2]);
}
return params;
}
This is referred to as Cache Busting.
The browser will cache the file, including the querystring. Next time the querystring is updated the browser will be forced to download the new version of the file.
There are various types of cache-busting, for example:
Static
Date/Time
Software Version
Hashed-Content
I've wrote an article on cache busting previously which you may find useful:
http://curtistimson.co.uk/front-end-dev/what-is-cache-busting/

Categories

Resources