Serving static files efficiently

You can further speed up static file serving by exploiting client-side caching. The idea is to send the client a version-specific URL for static files, and tell the client that it may cache that data forever. When the underlying file changes, your Webware app generates a new URL. This reduces traffic to the server, but more importantly, it can result in noticeably faster response at the client end.

This requires co-operation from Apache version 2. Here's the details:

Configure apache-2 so that urls like /@X/... are mapped to /..., and the client is told it may cache the result for a long time:

RewriteRule ^/@[^/]+/(.+)$        /$1      [L,E=VERSIONED_FILE:1]
Header add "Expires" "Thu, 10 Nov 2016 23:30:00 GMT" env=VERSIONED_FILE
Header add "Cache-Control" "max-age=315360000" env=VERSIONED_FILE

Modify your webware app to prefix version info to your static URLs. For example, for data that almost never changes, like images, return URLs like /@0/images/foo.gif:

# Apache serves image data out of /images.
# Put this in an app-wide config file:
images_url = '/@0/images'
...
self.write('<img src="%s/foo.gif" ... >' % images_url)

If such an object really does change, change images_url to /@1/images and restart webkit.

For files that occasionally do change, like CSS and javascript, set the version prefix to the underlying file's modification time. A function like this is useful:

# Let's assume the URL /static contains
# static file data served by Apache 2.
static_dir = '/var/www/myapp/static'  # filesystem path to /static

def static_url(thing):
    path = '%s/%s' % (static_dir, thing)
    modtime = os.path.getmtime(path)
    return '/@%x/static/%s' % (modtime, thing)

# Use it like so:
self.write('<script type="text/javascript" src="%s"></script>' % static_url('foo.js'))

Thanks to Cal Henderson for the original idea.

-- KenLalonde - 20 November 2006