CommonJS for Sprockets
CommonJS modules are a way of encapsulating and packaging up JavaScript files to ensure they're name-spaced and loosely coupled, a crucial aspect to ensuring JavaScript code quality and maintainability.
Traditional JavaScript module management is very manual, often using a single namespace for the whole app. In my opinion this doesn't go far enough - scripts end up being tightly coupled, there are accidental globals and code quickly descendes into spagetti.
CommonJS modules address all these problems by adding explicit requiring and exporting, allowing you to quickly see inter-dependencies between files.
The module format consists of two things:
- Loading in files using
require()
, - Explicitly exposing properties using
module.exports
.
However, integrating a JavaScript module workflow into a framework like Rails is not a trivial task. Well, until now...
I've been working with Josh Peek to integrate CommonJS modules into the library behind Rail's asset pipelining, Sprockets. The result is the gem sprockets-commonjs. Simply add the gem to your Gemfile, and you're good to go.
To specify that a script should be using CommonJS, just rename it from myscript.js
to myscript.module.js
. Any JavaScript or CoffeeScript files with module
in the filename will be automatically wrapped up as CommonJS modules, and can subsequently use the require and export API.
It's worth noting that modules won't be evaluated on page load, only when they're first required. Subsequent calls to require()
return a cached representation of whatever the module exported.
The gem doesn't do any static analysis of the AST, so you may have to double up require calls. However I think the average use case is using require_tree to concatenate files, so it won't be too much of a problem.
Having some sort of packaging and dependency system is crucial to modern and professional JavaScript development; CommonJS modules are a great solution. Perhaps if this gets traction, we'll see it in Sprockets core.