除了process.cwd()之外,是否有其他方法来获取当前项目根目录的路径名。Node是否实现了ruby的属性Rails.root之类的东西。我要找的是稳定可靠的东西。
当前回答
解决这个问题有很多种方法,每种方法都有其优缺点:
require.main.filename
从http://nodejs.org/api/modules.html:
当一个文件直接从Node运行时,require。Main被设置为它的模块。这意味着您可以通过测试require来确定文件是否已经直接运行。Main ===模块 因为module提供了一个filename属性(通常等价于__filename),当前应用程序的入口点可以通过检查require.main.filename来获得。
如果你想要应用的基目录,你可以这样做:
const { dirname } = require('path');
const appDir = dirname(require.main.filename);
优点与缺点
这种方法在大多数情况下都很有效,但如果你使用pm2之类的启动器或运行mocha测试,这种方法就会失败。这在使用Node.js ES模块时也不起作用。Main不可用。
module.paths
Node将所有模块搜索路径发布到module.paths。我们可以遍历这些,选择第一个解出来的。
async function getAppPath() {
const { dirname } = require('path');
const { constants, promises: { access } } = require('fs');
for (let path of module.paths) {
try {
await access(path, constants.F_OK);
return dirname(path);
} catch (e) {
// Just move on to next path
}
}
}
优点与缺点
这有时可以工作,但在包中使用时不可靠,因为它可能返回包安装所在的目录,而不是应用程序安装所在的目录。
使用全局变量
Node有一个全局命名空间对象,叫做global -你附加到这个对象上的任何东西都将在你的应用程序中的任何地方可用 ),你可以只定义一个全局变量:
// index.js
var path = require('path');
global.appRoot = path.resolve(__dirname);
// lib/moduleA/component1.js
require(appRoot + '/lib/moduleB/component2.js');
优点与缺点
始终如一地工作,但你必须依赖全局变量,这意味着你不能轻易重用组件等。
process.cwd ()
这将返回当前工作目录。完全不可靠,因为它完全依赖于进程从哪个目录启动:
$ cd /home/demo/
$ mkdir subdir
$ echo "console.log(process.cwd());" > subdir/demo.js
$ node subdir/demo.js
/home/demo
$ cd subdir
$ node demo.js
/home/demo/subdir
app-root-path
为了解决这个问题,我创建了一个名为app-root-path的节点模块。用法很简单:
const appRoot = require('app-root-path');
const myModule = require(`${ appRoot }/lib/my-module.js`);
app-root-path模块使用了几种技术来确定应用程序的根路径,考虑到全局安装的模块(例如,如果你的应用程序运行在/var/www/,但模块安装在~/.nvm/ v2 .x.x/lib/node/)。它不会在100%的情况下工作,但在大多数常见的情况下都会工作。
优点与缺点
在大多数情况下不需要配置即可工作。还提供了一些很好的额外方便的方法(参见项目页面)。最大的骗局是,如果出现以下情况,它就不会起作用:
你用的是启动器,比如pm2 并且,该模块没有安装在你的应用程序的node_modules目录中(例如,如果你全局安装它)
您可以通过设置APP_ROOT_PATH环境变量或在模块上调用. setpath()来解决这个问题,但在这种情况下,您可能最好使用全局方法。
NODE_PATH环境变量
如果你正在寻找一种方法来确定当前应用程序的根路径,上述解决方案之一可能最适合你。另一方面,如果您试图解决可靠地加载应用程序模块的问题,我强烈建议查看NODE_PATH环境变量。
Node的Modules系统在不同的位置寻找模块。其中一个位置是process.env. exe。NODE_PATH点。如果您设置了这个环境变量,那么您就可以使用标准模块加载器要求模块,而不需要进行任何其他更改。
例如,如果你将NODE_PATH设置为/var/www/lib,下面的代码就可以正常工作:
require('module2/component.js');
// ^ looks for /var/www/lib/module2/component.js
一个很好的方法是使用npm:
{
"scripts": {
"start": "NODE_PATH=. node app.js"
}
}
现在你可以用npm start启动你的应用程序,你就成功了。我将其与我的强制节点路径模块结合起来,这可以防止在没有设置NODE_PATH的情况下意外加载应用程序。更多关于环境变量的控制,请参见checkenv。
有一个问题:NODE_PATH必须在节点应用程序之外设置。你不能做process.env之类的事情。NODE_PATH = path.resolve(__dirname),因为模块加载器在应用程序运行之前缓存了它要搜索的目录列表。
[增加4/6/16]另一个非常有前途的模块,试图解决这个问题是波浪。
其他回答
简单:
require('path').resolve('./')
获得全局根的最简单方法(假设你使用NPM来运行你的node.js应用程序' NPM start',等等)
var appRoot = process.env.PWD;
如果你想交叉验证上面的内容
假设你想交叉检查process.env.PWD与node.js应用程序的设置。如果您想要一些运行时测试来检查process.env的有效性。PWD,你可以用这段代码(我写的似乎工作得很好)交叉检查它。你可以用包中的npm_package_name交叉检查apot中最后一个文件夹的名称。Json文件,例如:
var path = require('path');
var globalRoot = __dirname; //(you may have to do some substring processing if the first script you run is not in the project root, since __dirname refers to the directory that the file is in for which __dirname is called in.)
//compare the last directory in the globalRoot path to the name of the project in your package.json file
var folders = globalRoot.split(path.sep);
var packageName = folders[folders.length-1];
var pwd = process.env.PWD;
var npmPackageName = process.env.npm_package_name;
if(packageName !== npmPackageName){
throw new Error('Failed check for runtime string equality between globalRoot-bottommost directory and npm_package_name.');
}
if(globalRoot !== pwd){
throw new Error('Failed check for runtime string equality between globalRoot and process.env.PWD.');
}
你也可以使用这个NPM模块:require('app-root-path'),它非常适合这个目的
尝试path._makeLong(“some_filename_on_root.js”);
例子:
cons path = require('path');
console.log(path._makeLong('some_filename_on_root.js');
这将返回你的节点应用程序的根目录的完整路径(与package.json相同的位置)
的过程。mainModule自v 14.0.0起已弃用。参考答案时,请使用require。主要部分,其余部分还在。
process.mainModule.paths
.filter(p => !p.includes('node_modules'))
.shift()
获取主模块中的所有路径,并过滤掉带有"node_modules"的路径, 然后获取剩余路径列表中的第一个。意外行为不会抛出错误,只是一个未定义的错误。
对我来说很好,即使在调用ie $ mocha时也是如此。
在npm的现代版本中,你可以在exports中添加一个条目,用作速记。注意,如果你想同时引用根目录本身和根目录下的文件,你需要分别使用./和./*:
package.json:
{
"imports": {
"#root": "./",
"#root/*": "./*",
...
},
...
}
/ index.js:
import {namedExport} from '#root/file.js'
/ file.js:
export const namedExport = {
hi: "world",
};
然后:
$ node --experimental-specifier-resolution=node index.js
你可以用constants.js文件进一步扩展它,在那里你可以使用上面答案中的一个方法,或者输入一个绝对路径,如果你需要路径本身的话
推荐文章
- 有没有办法修复包锁。json lockfileVersion所以npm使用特定的格式?
- 如何使用npm全局安装一个模块?
- 实时http流到HTML5视频客户端的最佳方法
- 使用node.js下载图像
- Node.js Express中的HTTP GET请求
- Node.js:将文本文件读入数组。(每一行都是数组中的一项。)
- npm犯错!错误:EPERM:操作不允许,重命名
- Node Sass还不支持当前环境:Linux 64位,带false
- 我如何添加环境变量启动。VSCode中的json
- 解析错误:无法读取文件“…/tsconfig.json”.eslint
- 在Node.js中'use strict'语句是如何解释的?
- 当WebSockets可用时,为什么要使用AJAX ?
- 使用过程。TypeScript中的env
- 如何找到哪些承诺未处理在Node.js UnhandledPromiseRejectionWarning?
- 如何卸载Yarn