Opinionated Programmer - Jo Liss's musings on enlightened software development.

Bundling JavaScript With Your Gem? Make It Contributor-Friendly!

Many Rails gems these days bundle third-party assets, JavaScript assets in particular.

Oftentimes gem authors simply dump .js files into their repository, sometimes even concatenated build products. It’s a simple solution, and with tools like Vendorer it doesn’t have to turn into a maintenance headache.

But this makes it hard for users of your gem to contribute to your asset upstream (that is, to the third-party code that you include). Imagine I am a user of your gem: If I want to fix a bug in your gem code, it’s easy: I can clone your repository, point the gem in my Gemfile at my checkout or fork (with :path or :git), hack away at your code, and send you pull requests, while all my changes are instantly live in my app. But I cannot do the same to fix a bug in the third-party code you are shipping, since the version you ship is almost never up-to-date with the upstream master. And if I cloned the upstream, I would have trouble getting my fix back into your gem so I can use it in my app immediately. By losing that instant gratification, I’m much less likely to contribute to the upstream.

Luckily, this is easy to fix: Include the upstream using a Git submodule. Then add a Rake task that copies or builds the files into vendor/assets.

Now it’s easy to contribute: I simply clone your repository and set :path as before, and then check out the master branch on the submodule. I can hack away and send pull requests to the upstream straight from the submodule, while at the same time my changes to the upstream will be live in my app through your gem.

I call this quality contributor-friendliness. It’s not so much a service to your users – most won’t even care – as it is to the upstream project. By making it easy to contribute through your gem, you have expanded the upstream’s base of potential contributors with your users.

I think making open source work better is worth the overhead of using submodules, even if dumping vendor files might be easier sometimes. Our upstream maintainers provide all this awesome code. Let’s be nice to them and make our gems contributor-friendly.

Update June 2012:

This has been used in practice in Konacha and jquery-ui-rails. It seems to be working well so far.

To see a working Rake task, check the :assets task in Konacha’s Rakefile.

One insight we’ve had is to always check in the generated asset files. This is necessary so your library can be used in Bundler like so:

gem 'foo', :git => '...'

Bundler obviously won’t run your build step, so everything needs to be checked in.