Caching assets in a Rails 3 app on Heroku

In Rails apps, you often have multiple css and javascript files. If you’re using the “javascript_include_tag” and/or “stylesheet_link_tag” helpers, you can let Rails automatically package multiple files into a single file by using the “:cache => true” option. I’m sure you’re already aware of this, but if not, you can read more about it here.

A problem arises when trying to deploy an app using this technique to Heroku due to their read-only filesystem constraint. If you’re familiar with Yahoo’s Best Practices for Speeding Up Your Web Site and related YSlow tool, you know that caching your assets is an important part of having a speedy site.

There are a lot of possible solutions to this problem hanging around, but none of them seemed 100% ideal for my situation. So, I asked if there is a preferred method of caching/packaging assets in a Rails 3 app on Heroku in the Heroku Google Group. Nothing much came up, so I did a bit of Googling and came across this Stack Overflow page that pointed me in the right direction.

I’ve written a couple of small rake tasks that have been working quite well for me. The first is the “rake deploy” task. So, now I use “rake deploy” instead of “git push heroku master” when I want to deploy to Heroku. This caches my assets, pushed to github, deploys to heroku, and notifies hoptoad about the deploy.

But the “rake cache_assets” task is what we’re really interested in here. This leverages the built-in functionality of Rails to cache your assets, so it works exactly as you’d expect. It’ll create the “all.js” and “all.css” automatically, because I’m using the “:cache => true” option in my helpers. It’ll commit those files (if they’ve been changed) and then when I set “config.action_controller.perform_caching = true” in my “config/environments/production.rb” file, my app will use the cached files automatically.

This is a great first step, but there’s still more that can be done. As Heroku’s David Dollar pointed out in the Google Group, one could package these assets up and upload them to S3, using CloudFront as a CDN, and telling Rails to use that as your asset host. I’ve talked about CloudFront before, and I’ve had nothing but positive experiences with it, so I might try this in the future (uploading to S3 with fog, of course). If you’re interested in collaborating on this, please drop me a line.