覆盖 require 函数。

35

是否有可能覆盖全局的require函数,影响到process级别?

据我所知,require函数作为参数提供给包装NodeJS脚本的函数:

(function (..., require, __dirname) { // something like this
   // The wrapped code
})(...);

有没有办法修改require函数?

(function () {
    var _require = require;
    require = function () {
        console.log("...");
        _require.apply(this, arguments);
    };
})();

这可能只会影响到所在的脚本。

我们如何在进程级别上修改它?


看起来6to5在其require hook中做了类似的事情。 - ssube
你可以尝试在主文件中重写global.requireglobal.require = function(){}。 - Ben Fortune
2
我很想知道为什么? - mscdex
@mscdex 我预料到这个问题了。 :-) 我稍后会向你展示。 - Ionică Bizău
2
不,require在Node中是模块特定的,这是不可能的。 - Benjamin Gruenbaum
显示剩余4条评论
4个回答

89
var Module = require('module');
var originalRequire = Module.prototype.require;

Module.prototype.require = function(){
  //do your thing here
  return originalRequire.apply(this, arguments);
};

1
完美运行。感谢这段代码片段。 - Syntax
刚刚看到了你的回答。很抱歉这么晚才标记您的答案!谢谢! - Ionică Bizău
请问我需要将这段代码放在哪里,以确保它被每个 require 调用调用(TypeScript)? - Ayyappa
这是一个有趣的解决方案,但你不觉得它有点不好吗?我正在努力为自己辩解使用它 :) - Krasimir

11

我已经将这个简单的模块抽象出来,它提供了一个条件接口来覆盖模块解析逻辑(并允许重置原始的模块解析逻辑)。https://github.com/gajus/override-require - Gajus

11

这里是基于@orourkedd的更安全的本地ES6解决方案,它就像所有require调用的事件监听器,看起来可能会替换require,但如果您仔细观察,实际上它是在说:require = require并拦截对它的调用,但返回原始行为。这只是Proxy()的数百万用途之一,它对我非常有用,例如在TypeScript中将"paths"映射到实际模块节点将解析的tsconfig。

我甚至可以说这不是“猴子补丁”,因为它处于语言的较低级别。

var Module = require('module');
Module.prototype.require = new Proxy(Module.prototype.require,{
    apply(target, thisArg, argumentsList){

        let name = argumentsList[0];

        /*do stuff to ANY module here*/

        if(/MyModule/g.test(name)){
            /*do stuff to MY module*/
            name = "resolveAnotherName"
        }

        return Reflect.apply(target, thisArg, argumentsList)
    }
})

哦,我忘了你也可以释放代理,所以这不是永久的。 - Adam Miles Crockett
你使用代理的事实并不影响它是猴子补丁的事实(并不是说在这里使用猴子补丁一定不好)。 - andrezsanchez
在你的回答中,你说你使用它使 tsconfig 的路径起作用。你能分享一下你的代码吗?我已经为 tsconfig 的路径挣扎了一个星期了。这真的会很有帮助。谢谢。 - TheWhiteFang

1
这是我找到的解决方案。如果有更好的解决方案,欢迎分享。
我创建了一个名为 req-modifier.js 的脚本:
module.exports = function (_args) {

    var _require = _args[1];
    function newRequire () {
        console.log("Require is called");
        return _require.apply(this, arguments);
    }          
    newRequire.__proto__ = _require;

    _args[1] = newRequire;
};  

然后我想从文件中修改require函数,我这样做:

require("./req-modifier")(arguments);

var foo = require("./foo");

限制在于我必须每次调用req-modifier函数。

1
限制在于我必须每次调用req-modifier函数。实际上,这意味着你必须从每个模块中调用你自己的东西,这并不是一个真正的解决方案。 - Benjamin Gruenbaum

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