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 »