There are many ways to cache static contents in a web site. Without playing with cache headers, you can use different techniques to change file name to be sure the browser is renewing his local cache.
El Pais for example use the querystring to do the trick
http://www.elpais.com/js/util_nuevo.js?update=201104251641
I prefer to change the file name
http://www.sears.ca/stores/combined.js.h355855108.pack
because there are a lot of different opinions about if all browsers consider querystring part of the URL.
Again there are a lot of different ways to change the filename in a page.
I like to change it in the build process to completely decouple the renaming process with the development and deployment process.
Usually you are working in a development environment using a code repository and a build server.
To generate javascript versioned filenames, you just have to slightly modify the checkout process adding an Ant task like this
<replaceregexp match=”javascript/([a-zA-Z0-9]+)\.js” replace=”javascript/\1.v${env.BUILD_NUMBER}.js” flags=”g”>
<fileset dir=”${source.dir}/${cvs.package}” includes=”**/*.jsp, **/*.jspf”/>
</replaceregexp>
This way when you checkout your application code from CVS for example, you can use the BUILD_NUMBER environment variable (Jenkins has this variable available for script for example) to generate a link like this
<script type=”text/javascript” src=”<c:out value=’${storeImgDirHostname}javascript/MessageHelper.v3344.js’/>”></script>
from the original one
<script type=”text/javascript” src=”<c:out value=’${storeImgDirHostname}javascript/MessageHelper.js’/>”></script>
using the very efficient replaceregexp Ant task.
Now you have changed all the javascript links in your JSPs, you only have to cheat the browser to always load the same javascript filename in the HTTP filesystem.
You can do this with a simple rewrite rule like
RewriteRule ^/wcsstore/(.*)\.v(.*)\.js$ /wcsstore/$1.js
This way anytime a user will ask the versioned javascript file link
<script type=”text/javascript” src=”<hostname>/javascript/MessageHelper.v3344.js”></script>
the HTTP server will return the file without versioning
<script type=”text/javascript” src=”<hostname>/javascript/MessageHelper.js”></script>
But with an important difference: reloading the file from the http server with use the cached version.
This strategy allows also to keep the same filename from the developer workstation to the production http server.
Last step is to add the expires rule to cache javascript contents for a year for example
ExpiresByType text/javascript “access plus 1 year”