O'Reilly

Prevent Your CSS and JavaScript Files From Being Cached

By on  

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.

O'Reilly Velocity Conference
Save 20% with discount code AFF20

Recent Features

  • CSS Gradients

    With CSS border-radius, I showed you how CSS can bridge the gap between design and development by adding rounded corners to elements.  CSS gradients are another step in that direction.  Now that CSS gradients are supported in Internet Explorer 8+, Firefox, Safari, and Chrome,...

  • CSS @supports

    Feature detection via JavaScript is a client side best practice and for all the right reasons, but unfortunately that same functionality hasn't been available within CSS.  What we end up doing is repeating the same properties multiple times with each browser prefix.  Yuck.  Another thing we...

Incredible Demos

  • Using Opacity to Show Focus with jQuery

    A few days back I debuted a sweet article that made use of MooTools JavaScript and opacity to show focus on a specified element. Here's how to accomplish that feat using jQuery. The jQuery JavaScript There you have it. Opacity is a very simple but effective...

  • CSS Custom Cursors

    Remember the Web 1.0 days where you had to customize your site in every way possible?  You abused the scrollbars in Internet Explorer, of course, but the most popular external service I can remember was CometCursor.  CometCursor let you create and use loads of custom cursors for...

Discussion

  1. 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. Catar4x: Ooooh, I like that even more.

  4. 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. 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. 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. @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. Heed the words of Souders!

    • Brett

      Sometimes using this method is a requirement, such as ensuring a user gets the correct file for the release version. I have done this by including sFileSrc + “?v” + SiteVersion. Dueing debug, to avoid caching this is simply replaced by a timestamp to ensure every load has the most recent copy of the file.

    • Brett

      *During debug, not Dueing

  9. 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. 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. 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. 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. 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. 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. 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. 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. 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. Big up!

    Thanks for the tip.

    I was totally freak out with Chrome cache.

    Cheers.

  26. 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. thank you for this nice post

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

  29. Chris

    Temporary Internet Files just caches the file with the date extension eg class.css?1304526

    I want to prevent any caching!

  30. Thanks for the tip! Done it using javascript as well

  31. Andrew

    Chis is absolutely right!
    just appending a random string just creates another cache entry…
    to test: empty your cache and see how it fills up.
    Headers are often ignored or only work (cache entry is deleted) once the browser is closed and not every browser interprets header directives the same way.
    As I said before empty your cache and see what is cached and whether you can read/extract it from the cache.

  32. Nice trick. But I’ve one question. I’ve included many js/jquery files as well as css files in my application. So is this affect on performance of my application ? because everytime it will force browser to load the latest js/css files.

  33. I’m not gay, but if I were, I could fall for a guy like you. THIS IS GENIUS.

  34. I would not advise you to do this, because you actually WANT your .js files to be cached. You only want to enforce an update, if there was a change. So, using a php-time function for generating query strings is surely not the best idea, since it creates a lot of unnecessary traffic. Also, filemtime is not the best idea, as it is slow. Still, i’d probably prefer this approach. Best is to use some deployment tool that takes care of updating the query string for files that changed.

  35. For cached there .htaccess. Which set rule for cached, what file will be cached and how long.

    If you dont have .htaccess, CSS or JS will not be cached.

    There is some text about .htaccess cached -> http://www.limecanvas.com/speed-up-your-website-using-caching-and-htaccess/

Wrap your code in <pre class="{language}"></pre> tags, link to a GitHub gist, JSFiddle fiddle, or CodePen pen to embed!

Recently on David Walsh Blog

  • Access Mac Camera by Command Line

    With all of my recent command line tutorials, I've really gotten excited about the shell's simplicity and realized the true power of using the underlying technology of pretty UIs.  Since I work from home, I spend a lot of time on video calls, so when...

  • Open Files from Command Line on OS X

    I'm as much of a fan of application UIs as anyone else but I'm finding myself working more and more from the command line lately.  Much of that is becoming obsessed with media manipulation but I'm forcing myself to use less UIs so that I...

  • Get Stock Quotes From Command Line

    When I conned my way into my first professional programming gig, I didn't really think much about money -- just that I was getting my foot in the door.  But as my career has gone on, I've been more aware of money, investing, and retirement.  I've recently...

  • Geolocation API

    One interesting aspect of web development is geolocation; where is your user viewing your website from? You can base your language locale on that data or show certain products in your store based on the user's location. Let's examine how you can...

  • Create an Image Preview from a Video

    Visuals are everything when it comes to media.  When I'm trying to decide whether to watch a video on Netflix, it would be awesome to see a trailer of some kind, but alas that isn't available.  When I'm looking to download a video on my computer,...