Rails Asset Cache

Rails 2.0 uses asset cache to combine multiple Javascript or CSS libraries to a single Javascript and single CSS file. This improves performance by reducing the number of HTTP requests.

As a follow up to our article on Minifying Your Rails Javascript, let's take a look at a new feature in Rails 2.0 that makes packaging your assets into a single file much easier.

Enabling Cache

We use asset helpers such as javascript_include_tag and stylesheet_link_tag in our layouts to include external Javascript and CSS files. One benefit of using these helpers is the ability to cache these resources. Asset cache is turned on when the perform_caching configuration option is set to true.

Rails applications default to having caching disabled during development, and enabled in production. We can change this in config/environments/development.rb to test out caching during development.

config.action_controller.perform_caching = true

Caching Assets

We enable asset caching in our applications using the :cache option in our helpers. We can cache Javascript files by doing the following:

<%= javascript_include_tag "prototype", "application", "effects",
                           :cache => "cache/all" %>

When caching is disabled, Rails will generate the normal references to these resources.

<script src="/javascripts/prototype.js?1197321216" type="text/javascript"></script>
<script src="/javascripts/application.js?1197321216" type="text/javascript"></script>
<script src="/javascripts/effects.js?1197321216" type="text/javascript"></script>

However when caching is enabled, Rails will generate a single external Javascript file in the location we specified. It will then reference this file instead of the original source files.

<script src="/javascripts/cache/all.js" type="text/javascript"></script>

As you can see in the above example, we're going to store our asset cache in subdirectories named cache/. This makes it easier to clear out the cache later on. Caching external CSS files works similar to the Javascript example:

<%= stylesheet_link_tag "typography", "layout", "color",
                        :cache => "cache/all" %>

Clearing Cache

Rails comes with some useful built-in tasks for clearing out temporary files under the tmp: rake namespace. Rails does not come with a built-in task for clearing out the asset cache. We'll add this ourselves by adding a new rake task named rake tmp:assets:clear. Create a new file in your Rails application named at lib/tasks/tmp.rake, and add the following code.

namespace :tmp do
  namespace :assets do 
    desc "Clears javascripts/cache and stylesheets/cache"
    task :clear => :environment do      
      FileUtils.rm(Dir['public/javascripts/cache/[^.]*'])
      FileUtils.rm(Dir['public/stylesheets/cache/[^.]*'])
    end
  end
end

The custom tmp:assets:clear task we added removes all files from both the javascripts/cache/ and stylesheets/cache/ directories. Let's give it a whirl:

$> rake tmp:assets:clear

Wrap Up

Using asset cache can significantly reduce the number of requests sent to the server for external CSS and Javascript files. Along with a good gzip strategy, this is an essential feature when working with large multi-file Javascript libraries.

For additional performance increases using asset helpers, check out Chad Fowler's write-up of Distributed Asset Hosts.