前言
上一篇中我们已经探讨了一下如何在node之中使用别名require模块,里面提到了几种HACK方法,这里来解释一下是通过什么原理hack的。
module模块
其实吧,读过module的源码就懂了…因为require是靠module模块实现的,所以几种hack方式都是依靠hack module模块来搞的。 因为很多人都有分享过module源码的解析,所以下面就不讲累赘的内容了 (以下用的代码来自于node6.5.0,包包只看了下6.x及以上的代码)
_initPaths
可以看到源码中,首先Module模块首先运行了_initPaths
方法
1 | Module._initPaths = function() { |
NODE_PATH
和当前app的node路径收集在了一起, 在后来查找文件位置的时候会从这些路径查找。知道了它会使用NODE_PATH
,所以可以设定NODE_PATH
来缩短一大堆../../
(其实我觉得如果可以修改modulePaths
变量就更好了,可惜是个变量,而且Module.globalPaths
这个变量根本没在用,摔!)
require
require模块用的方法就是:
1 | Module.prototype.require = function(path) { |
1 | // 假设我们想要这样简写 require('@/abc.js') |
_findPath
因为Module.prototype.require
调用了Module._load
方法,Module._load
方法调用了Module._resolveFilename
方法, 然后通过Module._findPath
方法获取模块地址,如果没有地址就会报错,所以可以hack_findPath
方法(就是node6.x&以上才有这个方法) 可以看到如果request变量(其实就是你写的require的路径)是绝对路径,paths就是['']
,
也就是说直接指定了模块了路径,可以省去下面一大堆和预设好的path拼来拼去的过程了,不过给paths增加可选的路径也是个方法 不过我比较怕懒,所以我直接就把路径拼成绝对路径:
1 | // 假设我们想要这样简写 require('@/abc.js') |
_nodeModulePaths + _resolveFilename
是的还有这种组合技,不过我觉得实在比较麻烦 = = 代码可以看这里module-alias 因为Module._nodeModulePaths
只会在Module._resolveFilename
成功之后和没有parent的时候调用,关改这个还不管用,
修改Module._resolveFilename
其实单用也可以,可以把传入的路径修改为绝对路径,然后Module._findPath
跑的时候就可以直接用了,其实和修改Module._findPath
一样
最后
我用的方法是修改_findPath
方法做到的,其中还添加了缓存什么的
这里安利一下自己的插件node-require-alias
支持node6.0以上
使用方法:
1 | const path = require("path") |
欢迎来PR(づ ̄3 ̄)づ╭❤~