Taking the asset pipeline out of Rails

April 29, 2014 Robbie Clutton

While exploring other languages, and frameworks, I found that I tend to miss some of the tooling that Rails provides. In some cases I’ve leveraged what was in that community, and in others I’ve tried to bring across some tools of Rails. While building a web application in Clojure, I wanted an asset pipeline so that I could use familiar tools such as SASS for stylesheets along with Compass, Bourbon, Neat and Groundwork for style libraries.

Let’s take a look at how an asset pipeline can be applied to non Rails projects. We’ll start with Rails itself, work our way down, and build it back up again.


The asset pipeline in Rails was extracted into a Gem sprocket-rails, which has the Rake tasks, URL helpers for Rails applications and the configuration for the Rails conventions of where files are, and how to handle them. More information on configuring Rails applications can be read in the asset pipeline guide. This is included by default when you depend on the Rails gem.


The sprockets gem is where the work takes place. Work such as compiling assets, creating digest files and manifests of output. It also includes directives such as //= require jquery, which are not in the Javascript or CSS specifications.

During my efforts to use Sprockets in Clojure, I did come across sprockets-standalone but I think with a little work, an application could just depend upon sprockets alone to build the assets.

Sprockets integrates with various libraries such as the YUI Compressor binding or Ulgifier binding to minimize and compress Javascript and CSS. Both of these tools ultimately depend upon a Javascript runtime such as Rhino or Node.

The sprockets gem does include Rack, Coffeescript and other compilers your non Ruby application may be interested in, so let’s go one level deeper.


Sass is a library which extends CSS to include variables, mixins and other fun stuff, and it’ll compile those files into CSS. It also supports compression which can be used in Rails through the rails-sass Gem, and configured using sprockets-rails for a Rails application.

Now Sass was originally written in Ruby, but now also has a C/C++ port called libsass.

Putting it back together again

There are broadly two ways to start using these tools in a non Ruby application: use some Ruby through either Rake, another Ruby based build tool or a custom Ruby script; or use a non-Ruby build tool like Grunt. This can prove to be slightly problematic as I found out. With new features introduced with new versions of both SASS and Compass, it can be troublesome to know which versions you need for your application to all work together.

I had originally started using Rake, but also explored Grunt, and I’ll detail what I found here.

A note on dependencies

You may see that the dependencies include Rails like app/assets/stylesheets paths. This is a consequence of some of these libraries being built for Rails almost exclusively. Looking at Bourbon, it’s Rails by default although it does show how to use it without Rails. Neat only shows how to run on Rails. If you compare that to Groundwork, it has a project which is just the framework, and another for the Rails implementation. I think this is a better approach, although a little more work for the maintainers.


Dependencies with Bundler

I had used Bundler to install dependencies, but now needed to know where the dependencies were installed into so I can add certain files onto the SASS load path. I’m sure there’s a way to programmatically use Bundler, but I shelled out to get the paths to load.

The Gemfile includes the libraries I want to include:

    gem 'bourbon'
    gem 'neat'
    gem 'compass'

The Rakefile adds those to the build path:

    require 'sass'
    bourbon_path = `bundle show bourbon`.strip
    Sass.load_paths << File.expand_path("#{bourbon_path}/app/assets/stylesheets")

If you’re installing dependencies into a vendor path, you’ll know where these files end up and won’t have to shell out to figure that out.

Dependencies with Bower

My Bower dependencies included the Stylesheet libraries I wanted to use. Notice I’m using compass-mixins which is a Github repository which is a fork of Compass to make it available to Bower.

      "dependencies": {
        "bourbon": ">=3.1",
        "neat": "1.1.0",
        "compass-mixins": "latest"

Then in the Rakefile, I could load those paths.

    require 'sass'
    Sass.load_paths << File.expand_path("bower_components/bourbon/app/assets/stylesheets")


Now the paths are setup, we can compile. I’m using sprockets-standalone, but with a little extra work this could be use Sprockets.

    require 'sprockets/standalone'

    Sprockets::Standalone::RakeTask.new(:assets) do |task, sprockets|
      task.assets   = %w(application.css)
      task.sources  = %w(resources/sass)
      task.output   = File.expand_path('resources/public/assets', Dir.pwd)
      task.compress = true
      task.digest   = true

This gives the assets:clean and the assets:compile Rake tasks, which compile and fingerprint the assets.

Bower + Grunt

Now with Grunt, we can use the Bower dependency as outline above. The Grunt plugins for the moment tend to favor small single use plugins so I found one grunt-contrib-sass to compile the SASS, and grunt-asset-fingerprint to add a MD5 based fingerprint to the file name.

    module.exports = function(grunt) {

      // Project configuration.
        pkg: grunt.file.readJSON('package.json'),
        sass: {
          dist: {
            options: {
              loadPath: [
            files: {
              'resources/public/assets/application.css': 'resources/sass/application.sass'
        assetFingerprint: {
          options: {
            algorithm: 'md5',
            manifestPath: 'resources/public/assets/manifest.json'
          dist: {
            src: ["resources/public/assets/application.css"],
            dest: "resources/public/assets/application.css"


      // Default task(s).
      grunt.registerTask('default', ['sass', 'assetFingerprint']);



What have we learnt? We’ve taken what I think is a pretty important part of developing and productionising a web application, and made it available to other consumers. Let’s be honest, Rails makes this look easy, but when we’ve pealed back the layers we can see it’s doing a lot for us. Making it available to non Rails code bases requires some work, but once setup it shouldn’t require much tweaking. We’ve also seen that others have replicated some aspects such as fingerprinting of the files.

I think we’ve also learnt that we shouldn’t be so afraid of exploring other frameworks, and rolling your sleeves up and figuring how how something works under the hood.

My other take away is that library maintainers should consider the wider community that a current framework that may be targeted. Looking at Bourbon and Neat, both projects are Rails centric, whereas Groundwork is agnostic but layers on a Rails specific gem for those consumers. I think that’s a nicer approach to adopt.

About the Author

Robbie Clutton

Robbie Clutton is the Head of Pivotal Labs in EMEA.

OMG, Stop using abbreviations!
OMG, Stop using abbreviations!

This past weekend, my sister sent me a text message that she was in “CH”. I assumed this meant Clinton Hill...

6 Easy Steps: Deploy Pivotal's Hadoop on Docker
6 Easy Steps: Deploy Pivotal's Hadoop on Docker

Pivotal HD engineer Jun Aoki shares how to set up Hadoop with SQL on Docker by setting up Pivotal HD and HA...