Reducing HTTP Requests: An idea for a plugin

    Tim Lucas

    Cal Henderson from Flickr recently posted Serving Javascript Fast, where he talks about the approach they use at Flickr to reduce the number of HTTP requests per page and efficiently propagating new changes to assets.

    In Rails 1.1 we get the propagation of changed assets for free: all URLs to static assets (javascripts, stylsheets, images) get their last modified timestamp appended to their URL. When an asset gets updated, the URL changes and all clients download the latest version.

    For example, the following code:

    <%= stylesheet_link_tag 'common' %>

    will generate something similar to:

    <link href="/stylesheets/common.css?1148952578" media="screen" rel="Stylesheet" type="text/css" />

    Though not as efficient as Flickr’s approach, it’s simple and works for most people.

    The other problem Cal addressed, reducing the number of HTTP requests, is not something we get for free in Rails. In fact, the default setup for a Rails application that uses has 4 javascript files. These four files don’t often change (only when you upgrade Rails), they are often all needed together and are often updated at the same time. Sound like a good candidate for reducing HTTP requests? Wouldn’t it be great if when we deployed our application to a production server we could concatenate these together and have our views point to the concatenated version, and it all happens automatically. Sounds like a good candidate for a plugin… let’s call it… CombinedAssets!

    CombinedAssets would consist of 2 parts:

    1. A rake task which will generate the concatenated files
    2. A view helper to output different asset URLs on the production server

    In your environment.rb file you’d declare some sets of assets:

    CombinedAssets.javascripts[:rails] = %w(prototype controls dragdrop effects)
    CombinedAssets.stylesheets[:yui] = %w(fonts reset grids)

    Then in your view you could simply call:

    <%= javascript_include_tag combined_javascripts(:rails) %>
    <%= stylesheet_link_tag combined_stylesheets(:yui) %>

    The output of which would look something like the following in development:

    <script src="/javascripts/prototype.js?1147878861" type="text/javascript"></script>
    <script src="/javascripts/controls.js?1147878861" type="text/javascript"></script>
    <script src="/javascripts/dragdrop.js?1147878861" type="text/javascript"></script>
    <script src="/javascripts/effects.js?1147878861" type="text/javascript"></script>
    <link href="/stylesheets/fonts.css?1147878863" media="all" rel="Stylesheet" type="text/css" />
    <link href="/stylesheets/reset.css?1147878863" media="all" rel="Stylesheet" type="text/css" />
    <link href="/stylesheets/grids.css?1147878863" media="all" rel="Stylesheet" type="text/css" />

    and the following in production:

    <script src="/javascripts/prototype_controls_dragdrop_effects.js?1147878861" type="text/javascript"></script>
    <link href="/stylesheets/fonts_reset_grids.css?1147878863" media="all" rel="Stylesheet" type="text/css" />

    That’s 5 less HTTP requests for new visitors.

    Of course we’d also need a rake task that actually concats the files together, and when combined with Capistrano you could have this happen automatically on the production servers during deployment.

    With a language as succinct as Ruby and a framework as flexible as Rails, half the fun is coming up with the most elegant solution. The fact that’s its usually so simple to implement is an added bonus.