Prevent Your CSS and JavaScript Files From Being Cached

Some websites use highly volatile, oft-changing CSS and JavaScript files. In the case of these files, it's important that the developer prevent browsers from caching them. How do we do that? By using a phantom querystring, of course. We'll use PHP to tack the current time onto the file reference.

The PHP

<link href="/stylesheet.css?<?php echo time(); ?>" rel="stylesheet" type="text/css" /&glt;
<-- RENDERS -->
<link href="/stylesheet.css?1234567890" rel="stylesheet" type="text/css" /&glt;
<script type="text/javascript" src="/site-script.js?<?php echo time(); ?>"></script>
<-- RENDERS -->
<script type="text/javascript" src="/site-script.js?1234567890"></script>

It's a very simple technique and doesn't affect your CSS or JavaScript code in any way.


Comments

  1. Drew Barontini

    Great tip! I never even thought of doing something like that to prevent caching.

  2. Catar4x

    On a spanish blog, I saw this function a long time ago :

    function version($file) {return
    $file.’?’.filemtime($file);}
    “…
    But, thanks for the javascript tip !

  3. David Walsh

    Catar4x: Ooooh, I like that even more.

  4. Chris Hope

    I covered what Catar4x posted some time back:
    http://www.electrictoolbox.com/javascript-css-file-timestamps/

    It’s a little wordy but covers the thinking behind it.

  5. Adriaan

    and doesn’t effect your CSS

    is supposed to be:

    and doesn’t affect your CSS

    On a more related note, I use a modified php script I found here: http://www.ejeliot.com/blog/72

    The script (as I’ve modified it) always produces the latest js and css, and then caches that until one of the included js or css files change.

  6. Eric Wendelin

    I often need to add a random query string after a resource when grabbing something via Ajax, because IE will try to cache all sorts of weird stuff.

    Excellent tip, Walsh.

  7. Jesus DeLaTorre

    @Eric add a no cache header to your ajax response.

    netvibes uses a version number based off their svn revision, just something else to consider.

  8. Zach Leatherman

    Heed the words of Souders!

  9. Christian

    As Zach points out, you shouldn’t use query strings to “bust caches”. Check out my Juicer project for a more complete solution. Combined with a far future expires header you’ll have a winning combination :)

  10. David

    Is there a way to do this in Coldfusion?

  11. Nacho

    I use names like myfile.v2.ext to all my static content and rename it to myfile.ext with mod_rewrite in Apache.
    Every time i change the script I increase the version number.
    no need to avoid caches

  12. Johan K

    How I started doing Javascript caching:

    Bundle all javascript calls automatically into 1 source, for example:

    bundle.js?js=js/mootools-core.js,js/mootools-more.js,js/run.js&m=17274278

    Where $_GET['js'] is a comma separated list of scripts, and $_GET['m'] is the sum of all modification-dates (to prevent caching, as you describe in your article, but using filemtime() instead of time() and sum it to account for all files)

    bundle.js is rewritten using .htaccess to bundle.php which takes care of concatenating, JSMinify-ing (!!) and caching of the javascript files. Additionally it implements request/response headers like etag and modified enabling me to even respond with header 304 (not modified)

  13. Chris Hope

    I really like Nacho’s idea and you could easily enough make a single rule so you don’t need to keep modifying the rule along the lines of this (untested, off the top of my head):

    RewriteRule /css/main.[0-9]+.css /css/main.css

    Then the css in the code looks something like this: /css/main.1189482039.css and you could use PHP etc to work out the timestamp based on the modification time, which I’ve posted about previously (see my earlier link in the comments). Then you never need to change anything manually.

    I’m going to write up a post about this on my blog tomorrow.

  14. Trent

    I’ve also found that doing this works well with mobile development as I’ve encountered content pages caching often.

    For the ColdFusion fix you could do something like:

    <cfoutput>#timeFormat(now(),’hhmmssL’)#</cfoutput>

  15. James

    How about using .htaccess for disabling js/css caching?

    <FilesMatch “\.(js|css)$”>
    Header unset Cache-Control
    </FilesMatch>

  16. Chris Hope

    The catch with not caching JS or CSS at all is that the browser is going to have to download a copy of the file(s) every single time you load a page. This will slow requests down etc so it’s better to use some other convention as other people have suggested here e.g. using a query string with the timestamp (which appears to be not particularly recommended due to proxy issues) or the version number in the filename.

    If you’re going to make the browser download the CSS/JS every time then you may as well just include it in the page itself so only one request needs to be made per page.

  17. Chris Hope

    As I mentioned in an earlier comment, I was going to write a post about using rewrite rules etc. You can read it here: http://www.electrictoolbox.com/force-reload-css-javascript-unique-filenames/

  18. Nacho

    You can go a step further by having a table with the MD5 of all your static content. Every time you make new changes, a script checks the MD5 of all files and if it changes, adds +1 to the version number.
    then generate all URLs with a function that appends the version of this table to the filename so you dont have to do anything

  19. Giorgio Sironi

    But why are you address the problem at php level? Apache (and all the servers that implements ETags) returns a 304 Not Modified http header if the file is old, and the correct response if file is modified (for Apache basing on modification date, inode, etc.).

  20. Permana Jayanta

    So that’s mean the string after ? on .css file … i’ve seen that on wordpress blog …

  21. Jason Arencibia

    I know this is old, but I just found the site reading up on jQuery and mootools and since I’m not the best with JS, I tend to have to change things a lot and caching can become an issue where your asking yourself did I upload that last change? lol

    adding the query string to files might be a simple way, but I thought I’d share what I have done! seems to work!

    I just turn all my javascript and css into php files and add this to the top of the file:

    then call it like this in the page header

  22. John K. Njue

    Man you’ve really assisted me.

    Your solution is great.

    Keep up the good job.

    I am a young developer concentrating of PHP Ajax applications.

    I prefer to use JQuery Javascript framework.

  23. kash

    this is a great solution thanks, but, i dont understand how to implement it, if i just want to stop javascript from being cached do i just paste this somewhere on my site head or very top:

    <script type="text/javascript" src="/site-script.js?">

    And, where on the code it says 'site-script.js' -is that where i put the name of the javascript i want it to stop caching? and what are these numbers for: "/site-script.js?1234567890"?

  24. kash

    the code didnt paste properly, its the 2nd code on top if this page.

  25. Nicolás

    Big up!

    Thanks for the tip.

    I was totally freak out with Chrome cache.

    Cheers.

  26. Webpaul

    It’s a good tip but you have to download the entire css and js each page of the website you are surfing. I don’t think it’s the best solution.
    Maybe you can add a parameter like a version number after the question mark and change it only when the css/js really change. What do you think?

  27. indiaparinam

    thank you for this nice post

  28. Daniel

    Just want to say thanks for the tip. This saved me from further self mutilation.


Be Heard!

Share your thoughts without being a jerk! And wrap your code in <code> tags, f00!

Name*:
Email*:
Website: