Backbone Boilerplate Vs. Rails Asset Pipeline

Posted by by Ben Teese

We recently shifted from Backbone Boilerplate to the Rails Asset Pipeline for generating the various assets (Javascript, CSS, HTML, images, etc) that comprise teamstuff.com, a single-page app. In this post I’ll talk about our motivations for making the shift, what we had to change to get there, and how the end result turned out.

I’m going to be briefly mentioning a lot of different toolchain components in this post. I won’t be able to go into much detail on each one, but will include links where appropriate.

Why make the switch?

So why did we make the transition from Backbone Boilerplate to the Rails Asset Pipeline?

Firstly, it’s worth noting that we were already using Rails to implement our back-end service, which delivers JSON from RESTful endpoints. However, we had initially decided to completely separate the front-end from the back-end because we believed that it would make it simpler to scale-up delivery of the front-end, and also not mean that the two codebases were coupled together.

With the front-end a separate codebase, we chose to use Backbone Boilerplate to structure it. It did great at generating the front-end for delivery when it was on a single page. However, we began to get requirements that our site generate other pages that used the same assets as the initial single-page app. At first, we implemented this by extending Backbone Boilerplate to effectively become a static site generator, but it started to get pretty unwieldy.

Given that we were already using Rails for the backend, knew that the Rails asset pipeline could also serve up our app, and that Rails would make it trivial to generate additional pages, we decided to shift everything over to be served up by Rails, figuring that our initial concerns about scaling and coupling were perhaps a little premature.

Gory Details

Now I’ll drill into how we made the transition, on a piece-by-piece basis.

Less/CSS

Using some sort of CSS-preprocessor is a good idea on any modern web project. Our project was using Less because that’s what Backbone Boilerplate uses by default. By default Rails supports Sass, so to switch to Less we changed our project to use the less-rails gem. Those Less files whose compiled CSS was being directly loaded by the browser had to have their suffixes changed from .less to .css.less so that the asset pipeline could pick them up and compile them. We also relocated our Less files to the place where the plugin was going to expect them to be.

RequireJS

Rails doesn’t do use any special Javascript packaging or dependency loading, instead opting for good-old concatenation. However, we were already using RequireJS thanks to Backbone Boilerplate. We didn’t want to have to stop using RequireJS modules at this late stage in the project. The requirejs-rails Gem was able to let us keep RequireJS in the picture.

Handlebars

Our app uses Handlebars extensively for client-side HTML templating. We were initially pre-compiling these using a Grunt task. Fortunately there’s a gem to also do this with Rails: handlebars_assets. The only change was that we had to rename the templates to have a .hbl suffix and move them.

We also had some Handlebars templates that were being used on the server-side to generate the static portions of the site. Although we probably could have found a way to keep using Handlebars for these templates, we elected to shift them to ERB instead, as it’s something of a standard for Rails and there was no duplication between these and our client-side templates.

QUnit

Our QUnit client-side Javascript test suite was pretty much able to run out-of-the-box after shifting to Rails. We did, however, write a simple Rake file for running our tests headlessly from the command-line with PhantomJS. This task also ensures that the server is running so that the tests can be served up to Phantom.

Sprite Generation

To reduce the number of images that needed to be downloaded for our app, we originally used Glue to generate sprites via a custom Grunt task. Ideally, we’d shift to using Compass to do this (it’s Ruby-based and Rails has better support for it) but for that to work it would probably make sense for us to shift to Sass first (Sass is what Compass is based on). As such, we haven’t gotten around to doing this yet.

What we did do was write a custom Rake task to trigger Glue. Glue also produces sprites in a directory structure that differs from that used by Rails, so we had to customise the CSS it produced to load background images from a different path.

The End Result

Two factors were important when migrating from Boilerplate to the Asset Pipeline: no degradation in performance, and no loss of efficiency in the development process.

Performance

In shifting to the Rails asset pipeline we were very mindful of not affecting performance. We had to be confident that scaling up delivery of the front-end would still be possible.

As it turns out, Rails’ support for static compilation of pages means that we haven’t had any performance issues. How do we know? We set up a JMeter test to measure the app load times in a production replica environment.

The Development Experience

In shifting to Rails we did not want to make the development process any more complicated. Shifting all of our app to Rails has simplified our development. We now have one technology stack and one toolchain. There’s no need to install or understand the Node-based stack that Backbone Boilerplate runs on.

The Rails asset pipeline dynamically compiles our Less files and Handlebars templates as we develop, so we don’t have to run grunt watch any more as a background task to compile them when they change. From my perspective at least, this is a win – it’s disturbing the number of times I forgot to start it or it crashed and I didn’t realise it, leaving me wondering why my changes weren’t being picked up anymore.

The only downside for us has been that RequireJS compilation for our production JS artefact is now much slower than it used to be. It used to take maybe 30 seconds, now it’s more like 5 minutes. We don’t know why this has happened, but it’s not a huge deal for us because it is only routinely done as part of a build from our CI box. Consequently, we haven’t looked further into it.

Conclusions

If you’re using Rails, you’d probably want a pretty good reason not to use the asset pipeline. The answer to most questions is ‘there’s a Gem for that’, and if you hit any hitches along the way there’s usually plenty of other people who have had similar problems already. If you’re in an all-JavaScript environment, Backbone Boilerplate is a fine choice. However, I’d be disinclined to use it with Rails unless you absolutely have to.