Aaron Yodaiken
Aaron Yodaiken

Reputation: 19551

custom `require` method in CommonJS (specifically Node)

Is it possible to define a custom require method in one module that can be called in another module?

For example, in x/x.js

exports.xrequire = function(path) {
   console.log("requiring " + path);
   require(path);
};

In y/hello.js

console.log("Hello, world!");

And then in y/y.js

var xrequire = require("../x/x.js").xrequire;
xrequire("hello.js");

When y.js is run, "Hello World" should be printed.

I know this seems like a bad idea, but I do have a legitimate reason to do it. ;)


The issue with this code is that it tries to load x/hello.js, not y/hello.js — I'd like it to work the same as the standard require.

Upvotes: 3

Views: 1508

Answers (2)

Lime
Lime

Reputation: 13569

You certainly could do this. It would successfully avoid modifying the global require.paths array which can pose problems at run time, and shouldn't have an issues with future releases.

You should be able to simply set up a model that you simple require into your current app. According to your example x.js should contain.

var relative = 'y/';
exports.xrequire = function(path) {
   console.log("requiring " + relative + path);
   return require(relative+path);
};

Then you can successfully use your custom require.

var xrequire = require('x.js'),
    hello = xrequire('hello.js');

I don't advise this, but if you wanted to be really sneaky, you could override the require function.

var require = xrequire;

I would definitely throughly document this inside your module if you plan to require :D this functionality, but it certainly does work.

EDIT:

Well you could test for the file and fallback to require if it doesn't exist.

var relative = 'y/';
exports.xrequire = function(path) {
   var ret;
   try{
     ret = require(relative+path);
     console.log("requiring " + relative + path);
   }catch(e){
     console.log("requiring " + path);
     ret = require(path);
   }
   return ret;
};

I think you could try adding process.cwd to the beginning of the require path to force looking in the correct directory first. In all honesty this would confuse most developers. I would advise just defining a namespace for your app and creating a special require function that retrieves only that namespaced apps special functions.

Upvotes: 1

Sean McMillan
Sean McMillan

Reputation: 10093

The CommonJs modules spec requires that require be named require, and be called with a string literal, to allow build tools to preload modules.

A specific implementation may allow you to do what you want, but it may fail on another implementation, or when you upgrade.

Edit: The above comes from my recollection when I was learning about commonJS modules -- It does not appear to be defined that way in the spec.

Upvotes: 0

Related Questions