Node.js 中的 require
API 在加载 commonjs 模块的时候,会做两个事情:
- 根据 Node.js 的算法,查找到对应的模块文件;
- 加载查找到的模块文件并运行。
这里,如果只是想执行第一步,但并不真的运行这个被找到的模块,可以使用 Node.js 提供的 require.resolve
API。具体的调用示例如下:
const modulePath = require('some-package');
console.log(modulePath);
上面代码中,modulePath
是一个完整的文件路径,指向的位置就是 some-package
这个模块的 entry 文件(定义在 package.json 的 main
中)。默认情况下,这个 require.resolve
的查找路径是和 require
API 一致的:在查找的时候,会从当前文件的目录开始,逐级往上查找 node_modules
目录下是否有需要的库。
举例来说,假设有下面这样一个目录结构:
A.js
node_modules
|- some-package
|- index.js
|- other-package
|- index.js
utils
|- B.js
node_modules
|- some-package
|- index.js
且,假设 A.js 的代码为:
require('./utils/B');
console.log('A: ', require.resolve('some-package'));
console.log('A: ', require.resolve('other-package'));
B.js 的代码为:
console.log('B: ', require.resolve('some-package'));
console.log('B: ', require.resolve('other-package'));
那么,输出的结果为:
B: utils/node_modules/some-package/index.js
B: node_modules/other-package/index.js
A: node_modules/some-package/index.js
A: node_modules/other-package/index.js
但有的时候,只是希望可以使用 Node.js 的查找算法,但是查找的目录位置,并不一定是从当前文件所在的目录开始的。这种时候,就需要用到 require.resolve
的第二个参数了:
require.resolve('some-package', {
paths: [
'where-to-start-searching',
'other-possible-search-location',
]
});
这里,paths
是一个数组,表示所有的搜索起始位置。Node.js 会依次以这些路径为起始点,查找各个层级往上的 node_modules 目录。一旦找到需要的库,就停止查找,否则就会一直往上直到根目录。到达根目录后,当前的查找就以失败告终。如果还有其他的查找路径,就会继续上面的操作,否则程序会抛出异常。
第二个参数的一个实际应用场景如下:假设有一个 CLI 可以用于代理执行 Webpack 命令,这时候就需要首先通过 require.resolve
命令找出当前执行 CLI 命令的目录内,Webpack 库在什么位置。然后才可以用 require
命令去加载真正在项目中使用到的 Webpack 版本,而不是 CLI 内部可能依赖的一个 Webpack 版本。
更多关于 require.resolve
命令的说明,可以参考官方的文档。