CommonJS Modules with Rhino

javascript |

UPDATE: This post originally covered the syntax for using CommonJS modules with Rhino 1.7R3. I’ve updated it to cover the syntax for Rhino 1.7R4.

Rhino, Mozilla’s Java based JavaScript implementation, has gotten a facelift recently. First, the source was moved from CVS to GitHub, where it joins all the JavaScript cool kids. Let’s hope this change brings some more lifeblood into the project.

Perhaps more significantly, the 1.7R3 release of Rhino brought support for loading CommonJS modules. The nice thing about this is that you can author server-side JavaScript modules and deploy them with a single, simple dependency: a cross-platform .jar file.

To see this in action, you can download the latest release and extract the archive. For this example, I’ll write a few simple math modules that provide add and subtract methods. Then we’ll run a main.js application that pulls in these modules.

The layout for these example files looks like this:

main.js
my_modules/
    math.js
    math/
        add.js
        subtract.js

First, here’s the add.js module:

exports.add = function(a, b) {
    return a + b;
};

This module doesn’t have any dependencies. It exports one method: add.

And now the subtract.js module:

var add = require("./add").add;
exports.subtract = function(a, b) {
    return add(a, -b);
};

For the sake of this example, the subtract.js module requires the add.js module to implement the subtract method. The require call uses a relative module locator. This makes the exports from add.js available locally.

Finally, to provide a nice API for our application to use, I’ll create a math.js module that exports both add and subtract. The math.js module looks like this:

exports.add = require("./math/add").add;
exports.subtract = require("./math/subtract").subtract;

That’s it. Now the main.js application script:

var math = require("math");
print("5 minus 3 is " + math.subtract(5, 3));

In this case, the require call uses an absolute identifier to pull in the math.js module’s exports. This means it will pull in the first math.js script found on the module search path (available as require.paths within a module).

To run my application, I invoke Rhino with the -module command line options.

$ java -jar rhino1_7R4/js.jar -modules my_modules main.js
5 minus 3 is 2

Note: With the Rhino 1.7R3 release, you needed to specify your main module with the -main option (e.g. java -jar rhino1_7R3/js.jar -modules my_modules -main main.js). The -main option is not required with 1.7R4 and later.

The -modules value is a path that becomes my module search path (use multiple -modules options for multiple paths). The last argument (main.js) is the path to my main application script.

Nothing fancy in this example, but it demonstrates the potential for scripting server-side applications with JavaScript modules using Rhino.

Related Posts (see all)

Topology Preserving Simplification Comments
Mocking the file system Comments
AngularJS Whitespace Guide Comments