Skip to the content...

Welcome to the David Walsh Blog. I'm a MooTools, Dojo, jQuery, CSS, and PHP Web Developer located in Madison, Wisconsin, United States. Please contact me if I can make your experience on my website better.

Prevent Your CSS and JavaScript Files From Being Cached

21 Responses »

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.

Discussion

  1. March 17, 2009 @ 10:41 am

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

  2. catar4x
    March 17, 2009 @ 11:04 am

    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. March 17, 2009 @ 11:07 am

    Catar4x: Ooooh, I like that even more.

  4. March 17, 2009 @ 1:17 pm

    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. March 17, 2009 @ 1:50 pm

    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. March 17, 2009 @ 2:22 pm

    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. March 17, 2009 @ 3:22 pm

    @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. March 17, 2009 @ 5:17 pm

    Heed the words of Souders!

  9. March 17, 2009 @ 5:42 pm

    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
    March 18, 2009 @ 12:13 am

    Is there a way to do this in Coldfusion?

  11. nacho
    March 18, 2009 @ 6:36 am

    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. March 18, 2009 @ 7:29 am

    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. March 18, 2009 @ 1:01 pm

    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. March 18, 2009 @ 2:44 pm

    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
    March 18, 2009 @ 3:32 pm

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

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

  16. March 18, 2009 @ 3:38 pm

    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. March 19, 2009 @ 12:59 pm

    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
    March 19, 2009 @ 3:04 pm

    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. March 23, 2009 @ 12:44 pm

    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. March 25, 2009 @ 3:55 am

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

  21. jason arencibia
    May 2, 2010 @ 5:11 am

    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

Be Heard!

Share your thoughts with fellow developers of all skill levels! I want to hear from you!

Name*:
Email*:
Website:  
Wrap your code with <code> tags, f00!