Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/node.js/36.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript Node.js:获取已安装npm包的(绝对)根路径 任务_Javascript_Node.js_Path_Npm_Package - Fatal编程技术网

Javascript Node.js:获取已安装npm包的(绝对)根路径 任务

Javascript Node.js:获取已安装npm包的(绝对)根路径 任务,javascript,node.js,path,npm,package,Javascript,Node.js,Path,Npm,Package,我正在寻找一种通用方法来获取Node.js中已安装的npm包的(绝对)根路径 问题 我知道require.resolve,但这将为我提供入口点(主模块的路径),而不是包的根路径 以bootstrap sass为例。假设它安装在本地项目文件夹C:\dev\my project中。然后我要找的是C:\dev\my project\node\u modules\bootstrap sassrequire.resolve('bootstrap-sass')将返回C:\dev\my project\nod

我正在寻找一种通用方法来获取Node.js中已安装的npm包的(绝对)根路径

问题 我知道
require.resolve
,但这将为我提供入口点(主模块的路径),而不是包的根路径

bootstrap sass
为例。假设它安装在本地项目文件夹
C:\dev\my project
中。然后我要找的是
C:\dev\my project\node\u modules\bootstrap sass
require.resolve('bootstrap-sass')
将返回
C:\dev\my project\node\u modules\bootstrap sass\assets\javascripts\bootstrap.js

我可以想出几种方法来获取包的根路径:

解决方案#1 这对于本地安装在
node\u modules
文件夹中的软件包很好。但是,如果我在一个子文件夹中,我需要解析
。/node\u modules/bootstrap sass
,而嵌套文件夹越多,问题就越复杂。此外,这不适用于全局安装的模块

解决方案#2 这将适用于安装在
node\u modules
文件夹中的本地和全局模块。正则表达式将匹配最后一个
节点\u模块
路径元素加上下面的路径元素。但是,如果将一个包的入口点设置为另一个包(例如
“main”:“
package.json
中的/node\u modules/sub-package”
),则此操作将失败

解决方案#3 此功能应适用于安装在
node\u modules
文件夹中的所有软件包

但是 我想知道这项相当简单的任务是否不能用一种更简单、更简单的方式来解决。在我看来,它应该已经内置到Node.js中了。有什么建议吗?

试试这个:

require.resolve('bootstrap-sass/package.json')
返回:

path_to_my_project/node_modules/bootstrap-sass/package.json 
现在可以去掉“package.json”路径后缀,例如:

var path = require('path') // npm install path
var bootstrapPath = path.dirname(require.resolve('bootstrap-sass/package.json'))

由于每个包都必须包含
package.json
文件,因此这应该总是有效的(请参阅)。

您不需要查找所需包的package.json文件,甚至不需要显式引用其位置

此外,您不应该这样做,因为没有确定的方法知道npm包将在npm的树中的何处结束(这就是为什么您转向
require.resolve
寻求帮助)

相反,您可以通过与标志一起使用来查询npm API(或CLI),这将:

显示可解析的输出,而不是树视图

例如:

$npm ls我的部门-p
…将输出如下内容:

/Users/me/my project/node\u modules/my dep
您应该知道,此命令还可以向stderr输出一些不相关的错误(例如,关于无关的安装)-要解决此问题,请激活
--silent
标志(请参见文档中的):

$npm ls我的部门-ps
可以使用将此命令集成到代码中,在这种情况下,最好在不使用
--silent
标志的情况下运行该命令,以允许捕获任何错误

如果捕获到错误,则可以决定其是否致命(例如,应忽略前面提到的关于无关包的错误)

因此,通过子进程使用CLI可以如下所示:

const exec=require('child_process')。exec;
const packageName='my dep';
exec(`npmls${packageName}--parseable`,(err,stdout,stderr)=>{
如果(!err){
console.log(stdout.trim());//->/Users/me/my project/node_modules/my dep
}
});
然后可以在异步流中使用(以及一些闭包魔术…),例如:

const exec=require('child_process')。exec;
const async=require('async');
异步瀑布([
npmPackagePathResolver('my-dep'),
(packagePath,回调)=>{
console.log(packagePath)//->/Users/me/my project/node\u modules/my dep
回调();
}
],(错误,结果)=>console.log('all done!');
函数npmPackagePathResolver(packageName){
返回(回调)=>{
exec(`npmls${packageName}--parseable`,(err,stdout,stderr)=>{
回调(err,stdout.trim());
});
};
}

您真正想解决的问题是什么(例如,为什么要尝试获得此路径)?您是否正在尝试获取模块中其他资源的路径?通常一个模块本身应该知道它自己的资源相对于它的位置在哪里,所以你只要让模块告诉你东西在哪里,它就可以给你答案。我想第一个问题是为什么你要找模块的位置而不是它的主文件第二个问题,npm有几个模块提供了它的功能,包括查找节点_模块的目录,比如我想用npm安装css框架(如bootstrap)并获取包含文件的路径(如.css/.scss/.svg/…)。read package tree需要一个包根路径作为第一个参数…但是,请记住,您试图实现的目标至少有一点不切实际(尽管这可能是最合理的做法)。谢谢!:)就目前而言,这似乎是最好的解决方案。与npm一起安装的包将始终具有package.json文件(请参阅)。因此
path.dirname(require.resolve('bootstrap-sass/package.json'))
起到了作用。是的,谢谢。我根据你的评论对答案进行了编辑,使其更加完整和完整。如果这对你有效,你能接受这个答案吗?谢谢。事实上,我没有看到任何关于无关软件包的输出,即使有无关软件包…可能是它们改变了行为,或者这些错误只发生在您使用
npm ls
而不指定软件包名称时,也就是说,
npm-ls--parseable
而不是
npm-ls某个包--parseable
@MattBrowne我认为这与撰写本文时的npm版本有关,正如您所怀疑的那样。
require.resolve('bootstrap-sass/package.json')
path_to_my_project/node_modules/bootstrap-sass/package.json 
var path = require('path') // npm install path
var bootstrapPath = path.dirname(require.resolve('bootstrap-sass/package.json'))