O'Reilly logo

Learning JavaScript Design Patterns by Addy Osmani

Stay ahead with the world's most comprehensive technology and business learning platform.

With Safari, you learn the way you learn best. Get unlimited access to videos, live online training, learning paths, books, tutorials, and more.

Start Free Trial

No credit card required

CommonJS

The CommonJS module proposal specifies a simple API for declaring modules that work outside of the browser (such as on the server). Unlike AMD, it attempts to cover a broader set of concerns such as IO, filesystem, promises, and more.

Originally called ServerJS in a project started by Kevin Dangoor back in 2009, the format was more recently formalized by CommonJS, a volunteer working group that aims to design, prototype, and standardize JavaScript APIs. To date, they’ve attempted to ratify standards for both modules and packages.

Getting Started

From a structure perspective, a CommonJS module is a reusable piece of JavaScript that exports specific objects made available to any dependent code. Unlike AMD, there are typically no function wrappers around such modules (so we won’t see define here, for example).

CommonJS modules basically contain two primary parts: a free variable named exports, which contains the objects a module wishes to make available to other modules, and a require function that modules can use to import the exports of other modules (Examples 11-9, 11-10, and 11-11).

Example 11-9. Understanding CommonJS: require() and exports

// package/lib is a dependency we require
var lib = require( "package/lib" );

// behaviour for our module
function foo(){
    lib.log( "hello world!" );
}

// export (expose) foo to other modules
exports.foo = foo;

Example 11-10. Basic consumption of exports

// package/lib is a dependency we require
var lib = require( "package/lib" );

// behaviour for our module
function foo(){
    lib.log( "hello world!" );
}

// export (expose) foo to other modules
exports.foo = foo;

Example 11-11. AMD-equivalent of the first CommonJS example

define(function(require){
   var lib = require( "package/lib" );

    // some behaviour for our module
    function foo(){
        lib.log( "hello world!" );
    } 

    // export (expose) foo for other modules
    return {
        foobar: foo
    };
});

This can be done as AMD supports a simplified CommonJS wrapping feature.

Consuming Multiple Dependencies

app.js:

var modA = require( "./foo" );
var modB = require( "./bar" );

exports.app = function(){
    console.log( "Im an application!" );
}

exports.foo = function(){
    return modA.helloWorld();
}

bar.js:

exports.name = "bar";

foo.js:

require( "./bar" );
exports.helloWorld = function(){
    return "Hello World!!"
}

Is CommonJS Suitable for the Browser?

There are developers that feel CommonJS is better suited to server-side development, which is one reason there’s currently a level of disagreement over which format should and will be used as the de facto standard in the pre-Harmony age moving forward. Some of the arguments against CommonJS include a note that many CommonJS APIs address server-oriented features that one would simply not be able to implement at a browser level in JavaScript—for example, io, system and js could be considered unimplementable by the nature of their functionality.

That said, it’s useful to know how to structure CommonJS modules regardless so that we can better appreciate how they fit in when defining modules that may be used everywhere. Modules that have applications on both the client and server include validation, conversion, and templating engines. The way some developers are approaching choosing which format to use is opting for CommonJS when a module can be used in a server-side environment and using AMD if this is not the case.

As AMD modules are capable of using plug-ins and can define more granular things like constructors and functions, this makes sense. CommonJS modules are only able to define objects that can be tedious to work with if we’re trying to obtain constructors out of them.

Although it’s beyond the scope of this section, you may have also noticed that there were different types of require methods mentioned when discussing AMD and CommonJS. The concern with a similar naming convention is of course confusion, and the community is currently split on the merits of a global require function. John Hann’s suggestion here is that rather than calling it require, which would probably fail to achieve the goal of informing users about the different between a global and inner require, it may make more sense to rename the global loader method something else (e.g., the name of the library). It’s for this reason that a loader like curl.js uses curl() as opposed to require.

With Safari, you learn the way you learn best. Get unlimited access to videos, live online training, learning paths, books, interactive tutorials, and more.

Start Free Trial

No credit card required