Olov Lassus

JavaScript modules in shells, browsers, everywhere!

04 Apr 2011

This is the technique I’m using to get JavaScript module support in the console and in the browser, with the same code base. It’s tested with the following JS shells: js (SpiderMonkey), jsc (JavaScriptCore), v8/d8 and node. It’s useful since it lets you stay in the console as much as you want to and it enables you write once, run everywhere (that’s what they said).

I’m using it in JSShaper. Do you find it useful? Do you know of a better way? Let me know!

In your program top-level file, define require as follows. It’s now either defined as the built-in require or a version of the built-in load that returns nothing.

var require = require || function(f) { load(f); };

In all other files, when you need to import a module such as Fmt, do it like this. The first || clause is truthy (and thus assigned) when Fmt is already defined in the global namespace, the second when require is CommonJS-style and the third when require wraps load (thus Fmt is now in the global namespace).

var Fmt = Fmt || require("./fmt.js") || Fmt;

Finally, your modules should have the following structure, for example Fmt:

var Fmt = (function() {
    // ...
    return ...;
})();
if (typeof exports !== "undefined") {
    module.exports = Fmt;
}

Voila, your module-separated program now works in the JS shells and the browsers! For the browsers, just include (or concatenate) the scripts in dependency-order. This isn’t a dynamic JS loader - if you want one there’s gazillions of them.

Here are the underpinnings for the curious:

Show comments (reddit)


Follow me on Twitter

« Making v8bench restrict mode clean    ↑ Home     »