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:
node, require is a built-in function used to load CommonJS-style modules. require reads code from disk and evaluates it. It returns the object exported by the module. The module lives in its own namespace. There’s no load function.v8, load reads code from disk and evaluates it in the global namespace. It returns nothing (undefined). There’s no require function.js, load reads code from disk and evaluates it in the global namespace. It returns the load function itself (don’t ask me why). There’s no require function.jsc, load reads code from disk and evaluates it in the global namespace. It returns the value of the last statement in the file (or something like it). There’s no require function.load or require functions.
Follow me on Twitter
« Making v8bench restrict mode clean ↑ Home I made JSLint restrict mode clean. Here's what I found »