Faster Capistrano deployments

“Release early, release often”, a philosophy that emphasizes the importance of early and frequent releases in creating a tight feedback loop.

I’ve been trying to push my code to production as often as possible. But I’ve been having a problem with the asset pipeline. From the moment Capistrano hits the deploy:assets:precompile task, it might take a few minutes to run, depending on the number of assets you have. These slow deployments lead to me not deploying as often as I wish.

The main reason for this is that Capistrano precompiles all the assets even when they haven’t changed. On top of that, Rails generates assets twice, once for the digest version and once for the non-digest version.

This problem has been solved in Rails 4.0 due to the usage of a newer version of Sprockets and the new sprockets-rails dependency. So from Rails 4.0 and beyond, only changed assets will be precompiled on deployment.

Luckily, there is a solution for pre Rails 4 projects. Most custom build solutions exist in overwriting the Capistrano deploy:assets:precompile task and check through git if the assets have changed. Although this method will work, I’m not to keen on this, because this means, whenever extra functionality is added to the Capistrano precompile task, you most likely will have to change your custom task.

This is where turbo-sprockets-rails3 comes into play. This gem started out as a set of patches for sprockets-rails by Nathan Broadbent, which were not merged into master because the problems was already addressed in Rails 4.

So turbo-sprockets-rails3 claims the following:

  • speeds up your Rails3 rake assets:precompile by only recompiling changed assets, based on hash of their source files
  • only compiles once to generate both digest and non-digest assets

So in short, it would make your deployments faster after the initial deployment when no assets change.

So I’ve tried out a small test with one of my projects:

# Without tubo-sprockets-rails3
$ time rake assets:precompile RAILS_ENV=production
 real 1m35.240s
 user 1m9.395s
 sys 0m24.046s

# With turbo-sprockets-rails3 initial compile
$ time rake assets:precompile RAILS_ENV=production
 real 0m59.475s
 user 0m42.639s
 sys 0m16.063s

# With turbo-sprockets-rails3 without assets changes
$ time rake assets:precompile RAILS_ENV=production
 real 0m36.321s
 user 0m24.142s
 sys 0m11.336s

As you can see, adding the turbo-sprockets-rails3 gem, almost shaves off approximately 1 minute on precompiling the assets when nothing is changed.

I know that +- 30 seconds for precompiling still seems a long time, but in this case, I have +550 assets in the project. So decreasing my deployment time with about 1 minute made me a happy camper.