Idea about Expires header
Since the Steve Sounder’s High Performance Web Sites everyone knows to set far future Expires header on their static assets. What he didn’t say was how to deal with the file changes. You can’t instruct browser to download the file so you actually have to change the file’s URL.
Ruby on Rails handles this by automatically adding file’s timestamp as a query-string when using build-in helper methods — simple and not requiring server-side URLs rewriting. This is good enough, but only for files accessed from HTML directly and doesn’t work for files accessed from CSS: background images (unless you have dynamically generated styles).
I was thinking for some time about those background images, because they can be heavy and if you’re not using CSS sprites they make lots of requests. As I don’t like dynamically generated style sheets, I didn’t want any additional processing. And so it came to me: why not incorporate some changing value into the domain name? You could put a revision number or a timestamp in domain name of your statics server, just like this: static-1566.example.com. Both Rails and Django provide easy ways to change static assets domain.
This requires you to set-up wildcard subdomain, but is’s easier than processing CSS files. It works because url function in a style sheet is resolved using the style sheet’s own address.
PS: This is only a brain-dump — I didn’t test it.
Comments(10)
Might be easier to just version a path.
eg : /static-1234/style.css, /static-1234/image.png
and then reference the image as url(‘./image.png’) from the stylesheet. No need for wildcard domains (which are often inaccessible).
Great idea anyway. Might try to implement it.
I was thinking about Google App Engine (again!). GAE gives you wildcard subdomains for free and AFAIK doesn’t allow synlinks. But for dedicated servers versioned path might be better.
It’s an interesting idea. Have you tried implementing it in one of your
applications ?
@lbadura: No, not yet. I’ll be trying that in some time for my brand new application I’m developing as my Honours Project.
I am just patching URLs manually when appropriate (linking to
/some/thing-13.png or /other/style-21.css and using nginx rewrite rule to strip -(\d ) from static files), and don’t find it too troublesome, but I guess it depends on the application.
Your idea is interesting, but I find one drawback. When does this number in domain name change? If it is common for all files, then even resources which were not changed would need to be redownloaded. If it is different for every image/file, then there are no chances for keepalive connection, and the browser may hog your server as the limit of 2 connections to one address does not apply.
PS There always is a possibility to patch the urls using version control hooks or build script hooks….
Editing URLs by hand is tedious and can be forgotten (especially when one image is used in many places). Passing it to VCS hook requires writing some more or less sophisticated script and that’s as good as writing patch for Less (CSS preprocessor) to do that. And yes, my solution would force downloading every component after one change. I don’t say your hints are bad or my solution is better, it just happens that I have different priorities.
Tried it on the development version of KSM site (though with url prefix, not domain prefix). Works like a charm – most pages now require just a single request to fetch HTML, everything else is cached.
Nice to hear that!
We went with versioning the path and updating it based on the revision number in a Subversion repository. There’s different ways to do it, but this is automatic and working well for us
http://www.redrobotstudios.com/blog/2008/12/18/versioned-media-and-expires-headers-in-django/
Yet another recipe to serve static media in Django: http://www.peterbe.com/plog/serve-your-static-stuff-in-django-with-nginx