Demystifying CommonJS Modules

2010-10-18 00:00:00 +0100 by Alex R. Young

I've noticed a lot of misconceptions about CommonJS Modules coming from
server-side JavaScript newcomers. The momentum behind the Node community
is definitely a catalyst for this, although Node isn't to blame -- it's
very good at attracting newcomers to JavaScript.

If you're happily hacking with Node1 but feel
a bit intimidated by talk of CommonJS then
hopefully this article will elucidate the matter.


Although commercial companies and open source projects have been using
server-side JavaScript for a long time, the available environments had
fragmented. This article deals with Modules in particular, but even
with this singular example it's easy to see evidence of fragmentation.

For example, Rhino included files using
load(), a simple function that read a file and evaluated
it. In Node you'd use require(). What happens when you want
to run your Rhino code on Node?

It became obvious that a set of standards should be created to harmonise
interpreters, enabling us to use libraries across environments. The
CommonJS group was founded with the goal of creating a set of
specifications with this in mind.

As part of this initiative, CommonJS
was created to determine
how code should be loaded. Right now there are three specifications:
1.0, 1.1, and 1.1.1.


I remember reading this heated CommonJS discussion on the Node

I generally support the CommonJS idea, but let's be clear: it's hardly a specification handed down by the gods (like ES5); it's just some people discussing ideas on a mailing list. Most of these ideas are without actual implementations.

I'm happy you think that. A good example is the Module spec, which isn't easily implementable in the browser. One promise of CommonJS is to be able to share code between browser and server but at the same time they seem eager to loose backward-compatibility that browsers impose. I hope more effort will be put in that sense.

The political debates between implementors and CommonJS are interesting,
especially as Node has built up such a large community that may be
perceived by CommonJS as "locked in" to Node.

Another related thread of CommonJS discussions is whether or not
browsers are first class citizens -- getting modules to work as intended
in browsers isn't necessarily straightforward.

However, our problems are practical - I want to write software that as
many people can run as possible. If you're choosing a server-side
platform and like the idea of CommonJS adherence, then you'll want to
look at the implementations table on the

Modules: Basic Syntax

I prefer reading code to specs. This is what a module looks like:

exports.hello = function() {
  return 'Hello World'

This module makes the hello function available to the
outside world. It can be loaded using require:

var example = require('./example.js');

This will work in Narwhal and
Node although you won't see anything if you run it because it doesn't print the output.

This raises an interesting point: even simply printing the output makes
you get into a mess if you want to write portable JavaScript:


Works in Narwhal but displays an error in Node:

Error: print() has moved. Use require('sys') to bring it back.

And recently Node's core maintainers decided to move away from the sys
module name to

Specification Versions

As I mentioned, there are currently three versions of the Modules
specification. Version 1.1 adds some clarifications and extended

During the evolution of the specifications, there were discussions that
pulled the concept of modules from extremes that sounded like more like
package management systems, back to something simple like version 1.0

I think there needs to be a separation between package management and module loading.


We need to be able to share library code and even split our own projects
up into modular chunks. JavaScript didn't have this functionality out of
the box because it originated in browsers, where a script tag was
sufficient. As it turned out, JavaScript is a simple, flexible language
that we'd like to use elsewhere, so this deceptively easy problem needs
a lot of work to solve it satisfactorily.

Modules 1.1.1 has been approved, and implementations (like Narwhal) have appeared.

\[1\] Other environments are available!