Skip to content


Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
branch: gh-pages
Fetching contributors…

Cannot retrieve contributors at this time

242 lines (166 sloc) 13.073 kb
<div class='mp'>
<h1>CommonJS Module System</h1>
<p><a href="">CommonJS</a> is a community driven effort to standardize packaging of JavaScript libraries, known as <em>modules</em>. Modules written which comply to this standard provide portability between other compliant frameworks such as narwhal, and in some cases even browsers.</p>
<p>Although this is ideal, in practice modules are often not portable due to relying on apis that are currently only provided by, or are tailored to node specifically. As the framework matures, and additional standards emerge our modules will become more portable.</p>
<h2 id="Creating-Modules">Creating Modules</h2>
<p>Let's create a utility module named <em>utils</em>, which will contain a <code>merge()</code> function to copy the properties of one object to another. Typically in a browser, or environment without CommonJS module support, this may look similar to below, where <code>utils</code> is a global variable.</p>
<pre><code>var utils = {};
utils.merge = function(obj, other) {};
<p>Although namespacing can lower the chance of collisions, it can still become an issue, and when further namespacing is applied it can look flat-out silly. CommonJS modules aid in removing this issue by "wrapping" the contents of a JavaScript file with a closure similar to what is shown below, however more pseudo globals are available to the module in addition to <code>exports</code>, <code>require</code>, and <code>module</code>. The <code>exports</code> object is then returned when a user invokes <code>require('utils')</code>.</p>
<pre><code>var module = { exports: {}};
(function(module, exports){
function merge(){};
exports.merge = merge;
})(module, module.exports);
<p>First create the file <em>./utils.js</em>, and define the <code>merge()</code> function as seen below. The implied anonymous wrapper function shown above allows us to seemingly define globals, however these are not accessible until exported.</p>
<pre><code> function merge(obj, other) {
var keys = Object.keys(other);
for (var i = 0, len = keys.length; i &lt; len; ++i) {
var key = keys[i];
obj[key] = other[key];
return obj;
exports.merge = merge;
<p>The typical pattern for public properties is to simply define them
on the <code>exports</code> object like so:</p>
<pre><code>exports.merge = function(obj, other) {
var keys = Object.keys(other);
for (var i = 0, len = keys.length; i &lt; len; ++i) {
var key = keys[i];
obj[key] = other[key];
return obj;
<p>Next we will look at utilizing out new module in other libraries.</p>
<h2 id="Requiring-Modules">Requiring Modules</h2>
<p>There are four main ways to require a module in node, first is the <em>synchronous</em> method, which simply returns the module's exports, second is the <em>asynchronous</em> method which accepts a callback, third is the <em>asynchronous http</em> method which can load remote modules, and lastly is requiring of shared libraries or "node addons" which we will cover later.</p>
<p>To get started create a second file named <em>./app.js</em> with the code shown below. The first line <code>require('./utils')</code> fetches the contents of <em>./utils.js</em> and returns the <code>exports</code> of which we later utilize our <code>merge()</code> method and display the results of our merged object using <code>console.dir()</code>.</p>
<pre><code>var utils = require('./utils');
var a = { one: 1 };
var b = { two: 2 };
utils.merge(a, b);
<p>Core modules such as the <em>sys</em> which are bundled with node can be required without a path, such as <code>require('sys')</code>, however 3rd-party modules will iterate the <code>require.paths</code> array in search of a module matching the given path. By default <code>require.paths</code> includes <em>~/.node_libraries</em>, so if <em>~/.node_libraries</em>/utils.js_ exists we may simply <code>require('utils')</code>, instead of our relative example <code>require('./utils')</code> shown above.</p>
<p>Node also supports the concept of <em>index</em> JavaScript files. To illustrate this example lets create a <em>math</em> module that will provide the <code>math.add()</code>, and <code>math.sub()</code> methods. For organizational purposes we will keep each method in their respective <em>./math/add.js</em> and <em>./math/sub.js</em> files. So where does <em>index.js</em> come into play? we can populate <em>./math/index.js</em> with the code shown below, which is used when <code>require('./math')</code> is invoked, which is conceptually identical to invoking <code>require('./math/index')</code>.</p>
<pre><code>module.exports = {
add: require('./add'),
sub: require('./sub')
<p>The contents of <em>./math/add.js</em> show us a new technique, here we use <code>module.exports</code> instead of <code>exports</code>. Previously mentioned was the fact that <code>exports</code> is not the only object exposed to the module file when evaluated, we also have access to <code>__dirname</code>, <code>__filename</code>, and <code>module</code> which represents the current module. Here we simply define the module export object to a new object, which happens to be a function.</p>
<pre><code>module.exports = function add(a, b){
return a + b;
<p>This technique is usually only helpful when your module has one aspect that it wishes to expose, be it a single function, constructor, string, etc. Below is an example of how we could provide the <code>Animal</code> constructor:</p>
<pre><code>exports.Animal = function Animal(){};
<p>which can then be utilized as shown:</p>
<pre><code>var Animal = require('./animal').Animal;
<p>if we change our module slightly, we can remove <code>.Animal</code>:</p>
<pre><code>module.exports = function Animal(){};
<p>which can now be used without the property:</p>
<pre><code>var Animal = require('./animal');
<h2 id="Require-Paths">Require Paths</h2>
<p>We talked about <code>require.paths</code>, the <code>Array</code> utilized by node's module system in order to discover modules. By default node checks the following directories for modules:</p>
<li><code>&lt;node binary></code>/../../lib/node</li>
<p>The <strong>NODE_PATH</strong> environment variable is much like <strong>PATH</strong>, as it allows several paths delimited by the colon (<code>:</code>) character.</p>
<h3 id="Runtime-Manipulation">Runtime Manipulation</h3>
<p>Since <code>require.paths</code> is just an array, we can manipulate it at runtime in order to expose libraries. In our previous example we defined the libraries <em>./math/{add,sub}.js</em>, in which we would typically <code>require('./math')</code> or <code>require('./math/add')</code> etc. Another approach is to prepend or "unshift" a directory onto <code>require.paths</code> as shown below, after which we can simply <code>require('add')</code> since node will iterate the paths in order to try and locate the module.</p>
<pre><code>require.paths.unshift(__dirname + '/math');
var add = require('add'),
sub = require('sub');
<h2 id="Pseudo-Globals">Pseudo Globals</h2>
<p>As mentioned above, modules have several pseudo globals available to them, these are as follows:</p>
<li><code>require</code> the require function itself</li>
<li><code>module</code> the current <code>Module</code> instance</li>
<li><code>exports</code> the current module's exported properties</li>
<li><code>__filename</code> absolute path to the current module's file</li>
<li><code>__dirname</code> absolute path to the current module's directory</li>
<h3 id="require-">require()</h3>
<p>Although not obvious at first glance, the <code>require()</code> function is actually
re-defined for the current module, and calls an internal function <code>loadModule</code> with a reference to the current <code>Module</code> to resolve relative paths and to populate <code>module.parent</code>.</p>
<h3 id="module">module</h3>
<p>When we <code>require()</code> a module, typically we only deal with the module's <code>exports</code>, however the <code>module</code> variable references the current module's <code>Module</code> instance. This is why the following is valid, as we may re-assign the module's <code>exports</code> to any object, even something trivial like a string:</p>
<pre><code>// css.js
module.exports = 'body { background: blue; }';
<p>To obtain this string we would simply <code>require('./css')</code>. The <code>module</code> object also contains these useful properties:</p>
<li><code>id</code> the module's id, consisting of a path. Ex: <code>./app</code></li>
<li><code>parent</code> the parent <code>Module</code> (which required this one) or <code>undefined</code></li>
<li><code>filename</code> absolute path to the module</li>
<li><code>moduleCache</code> an object containing references to all cached modules</li>
<h2 id="Asynchronous-Require">Asynchronous Require</h2>
<p>Node provides us with an asynchronous version of <code>require()</code>, aptly named <code>require.async()</code>. Below is the sample example previously shown for our <em>utils</em> module, however non blocking. <code>require.async()</code> accepts a callback of which the first parameter <code>err</code> is <code>null</code> or an instanceof <code>Error</code>, and then the module exports. Passing the error (if there is one) as the first argument is an extremely common idiom in node for async routines.</p>
<pre><code>require.async('./utils', function(err, utils){
console.dir(utils.merge({ foo: 'bar' }, { bar: 'baz' }));
<h2 id="Requiring-Over-HTTP">Requiring Over HTTP</h2>
<p>Asynchronous requires in node also have the added bonus of allowing module loading via <strong>HTTP</strong> and <strong>HTTPS</strong>.
To require a module via http all we have to do is pass a valid url as shown in the <em>sass</em> to <em>css</em> compilation example below:</p>
<pre><code>var sassUrl = '',
sassStr = ''
+ 'body\n'
+ ' a\n'
+ ' :color #eee';
require.async(sassUrl, function(err, sass){
var str = sass.render(sassStr);
<pre><code>body a {
color: #eee;}
<h2 id="Registering-Module-Compilers">Registering Module Compilers</h2>
<p>Another cool feature that node provides us is the ability to register compilers for a specific file extension. A good example of this is the CoffeeScript language, which is a ruby/python inspired language compiling to vanilla JavaScript. By using <code>require.registerExtension()</code> we can have node compile CoffeeScript to JavaScript in an automated fashion.</p>
<p>To illustrate its usage, let's create a small (and useless) Extended JavaScript language, or "ejs" for our example which will live at <em>./compiler/example.ejs</em>, its syntax will look like this:</p>
<pre><code>::min(a, b) a &lt; b ? a : b
::max(a, b) a &gt; b ? a : b
<p>which will be compiled to:</p>
<pre><code>exports.min = function min(a, b) { return a &lt; b ? a : b }
exports.max = function max(a, b) { return a &gt; b ? a : b }
<p>First let's create the module that will actually be doing the ejs to JavaScript compilation. In this example it is located at <em>./compiler/extended.js</em>, and exports a single method named <code>compile()</code>. This method accepts a string, which is the raw contents of what node is requiring, transformed to vanilla JavaScript via regular expressions.</p>
<pre><code>exports.compile = function(str){
return str
.replace(/(\w+)\(/g, '$1 = function $1(')
.replace(/\)(.+?)\n/g, '){ return $1 }\n')
.replace(/::/g, 'exports.');
<p>Next we have to "register" the extension to assign out compiler. As previously mentioned our compiler lives at <em>./compiler/extended.js</em> so we are requiring it in, and passing the <code>compile()</code> method to <code>require.registerExtension()</code> which simply expects a function accepting a string, and returning a string of JavaScript.</p>
<pre><code>require.registerExtension('.ejs', require('./compiler/extended').compile);
<p>Now when we require our example, the ".ejs" extension is detected, and will pass the contents through our compiler, and everything works as expected.</p>
<pre><code>var example = require('./compiler/example');
console.log(example.min(2, 3));
console.log(example.max(10, 8));
// =&gt; { min: [Function], max: [Function] }
// =&gt; 2
// =&gt; 10
Jump to Line
Something went wrong with that request. Please try again.