问题描述
我正在寻找一种通用方法来获取Node.js中已安装的npm包的(绝对)根路径。
I'm looking for an universal way to get the (absolute) root path of an installed npm package in Node.js.
我知道 require.resolve
,但这会给出我是入口点(主模块的路径)而不是包的根路径。
I know about require.resolve
, but that will give me the entry point (path to the main module) rather than the root path of the package.
取 bootstrap-sass
作为一个例子。假设它在本地安装在项目文件夹 C:\ dev \ my-project
中。然后我要找的是 C:\ dev \ my-project \ node_modules \ bootstrap-sass
。 require.resolve('bootstrap-sass')
将返回 C:\dev \ my-project \ node_modules \ bootstrap-sass \\ \\ assets\javascripts\bootstrap.js
。
Take bootstrap-sass
as an example. Say it's installed locally in a project folder C:\dev\my-project
. Then what I'm looking for is C:\dev\my-project\node_modules\bootstrap-sass
. require.resolve('bootstrap-sass')
will return C:\dev\my-project\node_modules\bootstrap-sass\assets\javascripts\bootstrap.js
.
我可以想到几种方法如何获取包的根路径:
I can think of several methods how to get the package's root path:
var packageRoot = path.resolve('node_modules/bootstrap-sass');
console.log(packageRoot);
这对于本地安装在 node_modules $ c $中的软件包可以正常工作c>文件夹。但是,如果我在子文件夹中,我需要解析
../ node_modules / bootstrap-sass
,并且使用更多嵌套文件夹会更复杂。此外,这对全局安装的模块不起作用。
This will work fine for packages installed locally in node_modules
folder. However, if I'm in a subfolder, I need to resolve ../node_modules/bootstrap-sass
, and it get's more complicated with more nested folders. In addition, this does not work for globally installed modules.
var packageRoot = require.resolve('bootstrap-sass')
.match(/^.*[\/\\]node_modules[\/\\][^\/\\]*/)[0];
console.log(packageRoot);
这适用于 node_modules $ c中安装的本地和全局模块$ c>文件夹。正则表达式将匹配最后一个
)。 node_modules
路径元素以及以下路径元素的所有内容。但是,如果将包的入口点设置为另一个包(例如main: c> c> c中的./node_modules/sub-package
,则会失败.json
This will work for local and global modules installed in node_modules
folder. The regex will match everything up to the last node_modules
path element plus the following path element. However this will fail if a package's entry point is set to another package (e.g. "main": "./node_modules/sub-package"
in package.json
).
var escapeStringRegexp = require('escape-string-regexp');
/**
* Get the root path of a npm package installed in node_modules.
* @param {string} packageName The name of the package.
* @returns {string} Root path of the package without trailing slash.
* @throws Will throw an error if the package root path cannot be resolved
*/
function packageRootPath(packageName) {
var mainModulePath = require.resolve(packageName);
var escapedPackageName = escapeStringRegexp(packageName);
var regexpStr = '^.*[\\/\\\\]node_modules[\\/\\\\]' + escapedPackageName +
'(?=[\\/\\\\])';
var rootPath = mainModulePath.match(regexpStr);
if (rootPath) {
return rootPath[0];
} else {
var msg = 'Could not resolve package root path for package `' +
packageName + '`.'
throw new Error(msg);
}
}
var packageRoot = packageRootPath('bootstrap-sass');
console.log(packageRoot);
此函数适用于 node_modules $ c中安装的所有软件包$ c>文件夹。
我想知道这个相当简单的任务是否无法解决一种更简单,更少hacky的方式。对我而言,它看起来应该已经构建到Node.js中。有什么建议吗?
I wonder if this rather simple task cannot be solved in a simpler and less hacky way. To me it looks like something that should already be built into Node.js. Any suggestions?
推荐答案
试试这个:
require.resolve('bootstrap-sass/package.json')
返回:
path_to_my_project/node_modules/bootstrap-sass/package.json
您现在可以摆脱'package.json'路径后缀,例如:
You can now get rid of 'package.json' path suffix such as:
var path = require('path') // npm install path
var bootstrapPath = path.dirname(require.resolve('bootstrap-sass/package.json'))
因为每个包都必须包含 package.json
文件,这应该始终有效(参见)。
Since it is mandatory for every package to contain package.json
file, this should always work (see What is a package?).
这篇关于Node.js:获取已安装的npm包的(绝对)根路径的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!