Alex MacCaw

Ruby/JavaScript developer & entrepreneur. O'Reilly writer and open source developer. Working for Stripe.


I'm @maccman on Twitter.

I'm maccman on Github.

I'm oldmanorhouse on Skype.

I'm here on Linked in.

I'm here on Delicious.


Current OS projects:
Books/Sites/App's
I've created/written:
Email me

I am now blogging at blog.alexmaccaw.com

Sprockets Schmockets! CommonJS Is The Future For Rails JavaScript Packaging

June 30, 2011

Rails 3 has certainly had its detractors, but on the whole I think it's a huge improvement, with a brand new router, Action Mailer API and tons more. I'm also stoked that we're seeing some of Merb's influence when it comes to modularization and Rack.

One of these new features is the Asset Pipeline, a dependency management system using a integration version of Sprockets. This is one of the most heralded feature of the latest release, and the subject of DDH's latest keynote address.

Asset pipeline

Assets, such as JavaScript and CSS files, have been made first class citizens with their own app/assets folder, and Sprockets will now manage their dependencies intelligently using meta comments. This means that developers can structure their JavaScript and CSS files properly, so they don't end up in a huge slurry of unmaintainable and often redundant code.

# signal_id.js
//= require ./identity_validation
//= require ./toggle_credentials
//= require ./launchbar

This is an admirable aspiration, and indeed a great step forward. However, I can't help thinking that a huge opportunity was lost here, namely CommonJS modules. In my opinion, CommonJS modules are the best system for JavaScript dependency management. Here's a quote from my book JavaScript Web Applications explaining the benefits:

Not only have we split our code up into separate module components, the secret to good application design, but we've also got dependency management, scope isolation and namespacing.

If you've ever use Node or Python you've used CommonJS modules, whether you realize it or not. In a nutshell, CommonJS modules give you require and exports, letting you require other modules and expose variables to other modules. For example:

// example.js
exports.hello = function(){ return 'hello world'; };

// application.js
var example = require("example");
example.hello();

Although their syntax is simple, I can't emphasize enough how useful CommonJS modules are. They go a long way to solve conflicts and variable pollution problems in JavaScript - two absolutely critical pieces to JavaScript dependency management that Sprockets completely omits. Although Sprockets is arguably more compatible with existing JavaScript libraries, I think the Rails team should be pushing people towards a better solution, even if it has more of an initial learning curve.

However, I don't want to offer a lot of criticism without also offering a solution and so, dear reader, here it is: Stitch. Stitch is a Ruby port of the original Node library by Sam Stephenson, and brings CommonJS modules to your Rack and Rails programs.

Installation is simple, just specify the gem in your Gemfile, and include something like the following in your application's routes.rb:

match '/application.js' => Stitch::Server.new(:paths => ["app/assets/javascripts"])

Now if you browse to /applications.js, you'll see a bundled file of all the scripts present under app/assets/javascripts, wrapped in the CommonJS format. In other words you can start structuring your JavaScript files as CommonJS modules, and Stitch will make sure they'll all wrapped correctly.

Stitch will automatically compile any CoffeeScript files in the directory, and you can easily add additional compilers if required. Check out the documentation & source for more information.

In conclusion, CommonJS modules are an excellent way of managing JavaScript dependencies and using Stitch is an good way of integrating them with Rails.

Thanks to Peter Cooper for the title and advice, as well as Julio Ody and Elliot Kember.