42

Why not use it as a general component pattern for Javascript, including browser-executed Javascript?

At a glance, it seems to be a good way to modularize the project I'm currently working on, which consists of a large Javascript code-base, with lots of components, some of which interact with eachother.

Jonathan
  • 32,202
  • 38
  • 137
  • 208
  • Well commonjs is like adobe air i think , it is the api that wont run in a classic browser. but it is still javascript , with a different api. For instance in the browser you have dhtml or the dom , well in common js you have another api that is not relevant outside a browser. – user475434 Jan 23 '11 at 14:48

1 Answers1

73

CommonJS is definitely suitable for the browser, with some caveats. The CommonJS module pattern is quite nice (in my biased opinion), and is also a good stepping stone to the module system proposed for ECMAScript Harmony (the planned next release of the JavaScript language). Specifically, Harmony modules won't have access to the global ("window") object.

The reason that some people claim CommonJS modules are not suitable for the browser is that they can't be loaded via a <script> tag without some server-side assistance. For example, imagine you have a markdown library that exports a "convertToHTML" function. You could then make a module that looks like this:

var convertToHTML = require("markdown").convertToHTML;
exports.mangleSomeText = function() {
    // do something then call convertToHTML
}

This doesn't work via a script tag for a few reasons (the scope isn't wrapped, so convertToHTML would get attached to window, require wouldn't typically be defined and exports needs to be created separately for each module).

A client side library with a tiny bit of server side help could allow this to load via script tags easily. Or, a client side library that loads the script via XMLHttpRequest and does an eval() would also work, though the debugging experience is often not as good.

A fairly reasonable solution right now, though one that is also the subject of contentious debate among CommonJS members, is RequireJS. Using RequireJS, you can write your module like this:

define(function(require, exports, module) {

var convertToHTML = require("markdown").convertToHTML;
exports.mangleSomeText = function() {
    // do something then call convertToHTML
}

});

All we did was add that define() bit around the module. (You could likely make a server do that pretty easily as well, so that you don't even need to manually type the define part).

I've personally used RequireJS on a couple of projects now and find it an easy way to make use of CommonJS modules without a server-side bit. There are many other solutions and if you aren't reliant on running static JS files, standard CommonJS modules are a great way to go.

(ObDisclaimer: I started the CommonJS project, so I am clearly biased.)

Kevin Dangoor
  • 1,588
  • 11
  • 10
  • 3
    To be pedantic, ECMAScript Harmony modules does have access to the global object, just not the shared top level lexical scope. – Sebastian Markbåge Feb 26 '12 at 12:37
  • 3
    Is it possible to write a module that is compatible with both requirejs and commonjs? – Anderson Green Jan 03 '13 at 19:52
  • @AndersonGreen Yes it is, just detect the `define` and `exports` variable at the bottom and and both sets of code conditionally. – Sean Clark Hess Feb 05 '13 at 21:23
  • @SeanClarkHess I think there's a typo here. Can you explain what you meant by "and and both sets of code conditionally"? – Anderson Green Feb 06 '13 at 02:22
  • @AndersonGreen I wrote a blog post with an example of this: http://www.hacki.ly/post/45198957902/writing-javascript-for-both-node-and-browser – Wheeyls Mar 12 '13 at 17:44
  • Just to clarify, RequireJS implements AMD (Asynchronous Module Loading), which has two syntaxes, one of them very simmilar to CommonJS and tries to solve the same problem but focused mainly on the browser (ie, async) while CommonJS is more optimized for server-side (sync, file IO, etc). For simple differentiation see: http://unscriptable.com/code/AMD-vs-CommonJS/ – Alejandro García Iglesias Apr 12 '13 at 18:42