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.
Now I’ll drill into how we made the transition, on a piece-by-piece basis.
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
.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.
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.
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.
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.