Forum OpenACS Development: css and js versioning by url to avoid caching old ones

Last Monday I suggested on irc (https://openacs.org/irc/log/2008-06-09) to add a versioning feature for CSS and JavaScript files. The idea is not new at all. You can read about that here: http://www.stefanhayden.com/blog/2006/04/03/css-caching-hack/

The main problem is, when you fix something on a production server, by touching a CSS, your users (even your boss) get old versions, due to browsers and proxy's cache. You can refresh your browsers, of course, by pressing F5, or CTRL-R (Command+R). But if you don't do it, you could get "old" content for days.

I think the best way is to add the "file modification date" to the url, something like src="...../file.css?version=timestamp.

We should add this timestamp automatically. That way, whenever you change a css (or js) file, as soon as you upload it to the production server, you will get a new src link to that file.

That's the main idea. Now, let's talk about... if you think it's useful, how to do it, where should be done, etc.

I offer myself to do the implementation. I'd like to test it on a oacs 5.3, with lot of browsers, even with real users, but maybe the goal is to do it with template::head functions for next oacs release.

Ir order not to overload the server, the timestamp info could be cached, and flushed manually by developers when they upload by ftp, or automatically when upgrading a package, Or something similar to the "Changed" button form developer toolbar. When working on a development server, css refreshing could be very fast. On a production server, maybe autoflush could be once a day.

BTW, talking about developer-support, what about adding a CSS button?

I would recommend to combine this effort with the
following items:

 a) use expires header (via e.g. "ns_setexpires 300000")
    for css and js files (and maybe static images like 
    icons as well)

 b) add versioning via file-names (e.g. lists-5-3.css).
    when the files change in a local release, the 
    numbers should increment, when using pattern
    like *-5-3.css, it can be automated

The advantage of this approach is that the
user experience is much better, once the 
pages are cached. The site appears much quicker, 
oacs has to serve much less simple requests. 
Due to the  exipires header, the static files 
do not have to be validated and the page load
latency is significantly reduced.

For more background information, see
http://open.yahoo.com/performance/rules.html#expires

We are using expires setting in learn@WU since 
at least half a year with very good success (modified
the request processor to serve "resources" with
a three hours expires).

-gustaf neumann
I agree, we should try to include this in the toolkit, can you post your patch Gustaf? (looking forward to implement these stuff in Galileo)
Any experience with Etags?
http://open.yahoo.com/performance/rules.html#etags

Versioning of CSS & .js might be better with numbers as suggested in yahoo best practices, while the approach that Miguel suggest is more suitable for dynamic components (yahoo again). Anyway, certainly we need to adopt versioning in order to smoothly introduce any changes in css / .js in production sites.

BTW, anyone with idea on how headers flush can be acomplished?
http://open.yahoo.com/performance/rules.html#flush

I'm going to work on OpenACS 5.3 with that issues, due to that version is on our production server right now. That way, it could be used in older oacs versions (with no template::head api function and so on)

Once I had fixed all bugs, I could export that work to oacs 5.4 with its new templating system.

Gustaf, about "add versioning via file-name", it forces to rename files in CVS, doesn't it? or maybe it's a link to real filename?.

Putting in the expires setting sounds like a good idea, do you want to TIP it?
Rocael, below is the very simple patch for adding expires
to files in the resources directory. No, we are not using etags. 

Miguel, concerning CVS and filenames, i agree that a link 
sounds better to keep history. To keep maintenance low, 
one could write a small script and use maybe a tag in cvs
to create from the tag and the file-name a link... 

On the  other hand, if these resources are only changed when
the  version numbers of packages are upgraded, it would be quite 
easy to add the package_version to the resources path 
(similar to the yahoo YUI APIs approach)
http://.../resources/xowiki/0.88/xowiki.css 
such a change will lead to practically zero maintenance cost, 
the expires can be set to high values. Just people with
reverse proxies will not be to happy about this...

-gustaf neumann


===================================================================
RCS file: /cvsroot/openacs-4/packages/acs-tcl/tcl/request-processor-procs.tcl,v
retrieving revision 1.91
diff -u -r1.91 request-processor-procs.tcl
--- request-processor-procs.tcl    12 Oct 2007 07:33:45 -0000    1.91
+++ request-processor-procs.tcl    10 Jul 2008 22:27:03 -0000
@@ -488,6 +488,8 @@
         set path "[acs_root_dir]/www/resources/[join [lrange [ns_conn urlv] 1 end] /]"
     }
     if { [file isfile $path] } {
+        # set expires header to 15 Minutes
+        ns_setexpires 900
         ns_returnfile 200 [ns_guesstype $path] $path
         return filter_return
     } else {