【node】让require搜索非当前文件路径的逐级路径

 

node的require函数有一个规则,就是参数是一个模块的名字的时候,它会从当前文件的目录开始,一级级往上级目录搜索node_modules文件夹以及里面对应名字的模块。

比如当前文件的目录是 /etc/miao/papapa/doge ,在这个文件里面有一个 require('jiajia') ,那么require就会在以下位置寻找 jiajia模块

 

但是我要在非当前文件路径逐级向上查找模块的话,就没法直接这样用require了。

但我又不想自己写循环来实现这个功能,于是我开始打node自带模块的主意,既然require有那样的特性,那就一定有处理逐级路径的函数,于是我开始读module模块的源码。在里面各种find变量,找到了 Module._nodeModulePaths 这个函数,它的功能就是把一个路径分析成逐级路径的数组了。

然后又各种find,找到了处理require路径数组的地方,发现它是module.paths,那么问题解决了,只要用 Module._nodeModulePaths 先把路径拆成逐级路径,然后和module.paths合并就可以了。

这么一来就达到了require搜索非当前文件路径的逐级路径效果。

要注意的是module是当前context的实例,所以对它的操作不影响其父模块以及子模块,在这里修改的module.paths和其它模块无关,也就是说在其它模块会失去这个效果,除非在其它地方也执行以上代码。

我已经尝试了修改process.env[‘NODE_PATH’],因为源码里初始化module.paths的代码中也用到了这个环境变量,但是直接修改并没有什么用,到了子模块里依然是原来的NODE_PATH。

不知有没有办法让这个效果作用到全局。

【node】拦截process.stdout和process.stderr

由于解决这个问题花了我一些时间,所以记录一下说不定可以帮到其他人。

process.stdout是一个getter,所以我们不能用普通的替换来换掉process.stdout来拦截写入它的数据。同时,process.stdout是一个Writable Stream,所以也不能简单地直接从它里面获取写入的数据。

 

一开始我花了不少时间来研究怎么可以从这个Writable Stream里读出数据,但是这似乎太麻烦了,然后我甚至想到了利用child process来拦截数据。最后发现其实很简单,我们只要重新定义这个Getter就可以了。

这样我们就成功拦截到标准输出了,要注意,这段代码必须放在有任何输出之前,一旦在之前有了内容输出,它就没用了。

然后我们就可以自己决定怎么处理stdout了比如:

 

 

同理,process.stderr也可以这样拦截

【Javascript】清空数组

上面的清空方式虽然非常不合字面含义,不过还确实清空了。。。

 

 

 

这方法倒是符合字面含义了,不过这个操作会返回整个一个新的数组,所以可能性能不如上面的一种方法。