在CommonJS(特别是Node)中自定义`require`方法

3

是否可以在一个模块中定义一个自定义 require 方法使得其他模块可以调用?

例如,在x / x.js文件中:

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

在 y/hello.js 文件中。
console.log("Hello, world!");

然后在 y/y.js 中进行操作。

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

当运行y.js时,应该打印出“Hello World”。我知道这似乎是个坏主意,但我确实有一个合法的理由要这么做。;) 问题在于这段代码试图加载x/hello.js,而不是y/hello.js——我希望它能像标准的require一样工作。

当您尝试时,这个不起作用吗? - Paul Sonier
问题在于它试图加载 x/hello.js,而不是 y/hello.js — 我希望它能像标准的 require 一样工作。 - Aaron Yodaiken
2个回答

1

你当然可以这样做。这将成功避免修改全局的require.paths数组,这可能会在运行时引起问题,并且不应该对未来的版本产生影响。

你应该能够简单地设置一个模型,然后将其require到你当前的应用程序中。根据你的示例,x.js应该包含以下内容。

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

然后,您就可以成功地使用自定义的require了。

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

我不建议这样做,但如果你想非常“狡猾”,你可以覆盖 require 函数。

var require = xrequire;

如果您计划使用require这个功能,我建议您在模块内详细记录它,但它肯定是有效的。 编辑: 如果文件不存在,您可以测试并回退到require
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;
};

我认为你可以尝试在 require 路径的开头添加 process.cwd,以强制首先查找正确的目录。老实说,这会让大多数开发人员感到困惑。我建议只为您的应用程序定义一个命名空间,并创建一个特殊的 require 函数,仅检索该命名空间应用程序的特殊函数。


我希望它能够像默认的 require 一样使用标准相对路径,而不是硬编码的路径。谢谢 :) - Aaron Yodaiken
为什么?你是想让 require 冒泡吗? - Lime
你从未提到过 z %),难道你不会在 z 项目中使用 zrequire() 吗?我的意思是,你在项目 x 中使用了 xrequire。我有点觉得这个重写概念会增加更多的挫败感而不是帮助。 - Lime
@Lime 让我们在聊天室里继续这个讨论 - Aaron Yodaiken
很奇怪,我从未收到你打开聊天的通知。我回来查看你的帖子状态,发现你已经开了一个讨论...我在讨论中添加了一些评论。 - Lime
显示剩余3条评论

0

CommonJs模块规范要求require必须命名为require,并使用字符串字面量调用,以允许构建工具预加载模块。

特定的实现可能允许您做您想做的事情,但它可能在另一个实现或升级时失败。

编辑:上述内容来自我学习CommonJS模块时的回忆--在规范中似乎没有定义成这样。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接