Sea.js Manual & Documentation


Table of Contents


What is CommonJS?

CommonJS is a group with a goal of building up the JavaScript ecosystem. It has a mailing list of developers, just like you, who are dedicated to promoting portability and interoperability of JavaScript programs across JavaScript environments, from the server to the browser.

What are CommonJS Modules?

JavaScript doesn't have a built-in module system (not yet anyway), so the developers on the mailing list created their own. Traditional CommonJS modules might look like this:

math.js:

exports.add = function() {
  var sum = 0, i = 0, args = arguments, l = args.length;
  while (i < l) {
    sum += args[i++];
  }
  return sum;
};

increment.js:

var add = require('math').add;
exports.increment = function(val) {
  return add(val, 1);
};

program.js:

var inc = require('increment').increment;
var a = 1;
inc(a); // 2

Why Wrapped Modules?

If you look closely at the example above, you might notice that require is synchronous. That is, we're assuming that the module system will able to determine whether a given module is available (and initialize it) before the require call returns.

As it turns out, this is highly problematic for the browser.

Hands down, the best way to load JavaScript into the browser is by inserting <script> tags into the document. But script tag insertion is inherently asynchronous. As a result traditional CommonJS modules aren't going to work in this kind of environment.

One option would be to have a server-side component perform static analysis on the module code and return the module along with a list of its dependencies to the browser. This works pretty well, but it necessitates the installation of an external component along with all of the infrastructure that it depends on.

Instead, we wrap the module definition in a small amount of boilerplate, like this:

define(function(require, exports, module) {

  // The module code goes here

});

The boilerplate gives the module loader the opportunity to perform static analysis on the module code and dynamically generate a list of dependencies that must be resolved before the module code executes.

In order for static analysis to work, though, you'll need to follow a few simple rules.

If we wrap the traditional modules that we looked at previously, we get this:

math.js:

define(function(require, exports, module) {
  exports.add = function() {
    var sum = 0, i = 0, args = arguments, l = args.length;
    while (i < l) {
      sum += args[i++];
    }
    return sum;
  };
});

increment.js:

define(function(require, exports, module) {
  var add = require('math').add;
  exports.increment = function(val) {
    return add(val, 1);
  };
});

program.js:

define(function(require, exports, module) {
  var inc = require('increment').increment;
  var a = 1;
  inc(a); // 2
});

Some explanations are forked from FlyScript's Documentation. Thanks very much to Kevin H. Smith.