The Asset Pipeline in Sinatra

The spectacular asset pipeline that shipped with Rails 3.1 is an easy feature to get used to once you’ve started using it, and when writing light Sinatra apps it’s one feature that I miss enough to pull in. Initially, I’d boot up a Sprockets module directly in my application’s rackup file (that’s config.ru) and map it to a particular URL path. This approach works well, but makes a mess in the rackup file and offers little in terms of fine-grained control. More recently I’ve found that I can get better flexibility and clarity by running it from a custom Sinatra module.

Add Sprockets and Yahoo’s YUI compressor to your Gemfile:

gem "sprockets"
gem "yui-compressor"

# I find it well worth to include CoffeeScript and SASS as well
gem "coffee-script"
gem "sass"

Your assets file structure should look something like this:

+ assets
  + images
    - my-jpg.jpg
    - my-png.png
  + javascripts
    - app.js
    - my-scripts.coffee
  + stylesheets
    - app.css
    - my-styles.sass

app.js should load all other JavaScript assets in its directory (in the example structure above this will pick up my-scripts.coffee):

//= require_tree

app.css as well (includes my-styles.sass):

//= require_tree

The Sinatra module should look something like this:

class Assets < Sinatra::Base
  configure do
    set :assets, (Sprockets::Environment.new { |env|
      env.append_path(settings.root + "/assets/images")
      env.append_path(settings.root + "/assets/javascripts")
      env.append_path(settings.root + "/assets/stylesheets")

      # compress everything in production
      if ENV["RACK_ENV"] == "production"
        env.js_compressor  = YUI::JavaScriptCompressor.new
        env.css_compressor = YUI::CssCompressor.new
      end
    })
  end

  get "/assets/app.js" do
    content_type("application/javascript")
    settings.assets["app.js"]
  end

  get "/assets/app.css" do
    content_type("text/css")
    settings.assets["app.css"]
  end

  %w{jpg png}.each do |format|
    get "/assets/:image.#{format}" do |image|
      content_type("image/#{format}")
      settings.assets["#{image}.#{format}"]
    end
  end
end

Now use the assets module as middleware in config.ru, and delegate everything else to your main app:

use Assets
run Sinatra::Application

Posted on November 10, 2012 from the De Young Museum, San Francisco

About

My name is Brandur. I'm a polyglot software engineer and part-time designer working at Heroku in San Francisco, California. I'm a Canadian expat. My name is Icelandic. Drop me a line at brandur@mutelight.org.

Aside from technology, I'm interested in energy and how it relates to our society, travel, longboarding, muay thai, symphonic metal, and the guitar.

If you liked this article, consider finding me on Twitter.