一尘不染

从运行的node.js应用程序确定项目根目录

node.js

有没有比process.cwd()确定正在运行的node.js进程的根目录更好的方法?类似于Rails.root,但适用于Node.js。我正在寻找尽可能可预测和可靠的东西。


阅读 358

收藏
2020-07-07

共1个答案

一尘不染

有几种方法可以解决此问题,每种方法各有利弊:

require.main.filename

http://nodejs.org/api/modules.html

直接从Node运行文件时,require.main将其设置为module。这意味着您可以通过测试确定文件是否已经直接运行require.main === module

因为module提供了一个filename属性(通常等效于__filename),所以可以通过检查获得当前应用程序的入口点require.main.filename

因此,如果您想要应用程序的基本目录,则可以执行以下操作:

var path = require('path');
var appDir = path.dirname(require.main.filename);

优点缺点

这在大多数情况下都可以正常工作,但是如果您使用 pm2之 类的启动器运行应用程序或运行 mocha 测试,则此方法将失败。

全局X

节点有一个名为的全局命名空间对象global-您附加到此对象的任何对象都将在您的应用程序中的任何位置可用。因此,您可以在您index.js(或app.js您的主应用程序文件中使用任何名称)中定义一个全局变量:

// 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 的节点模块。用法很简单:

var appRoot = require('app-root-path');
var myModule = require(appRoot + '/lib/my-module.js');

应用程序根路径
模块使用多种不同的技术来确定该应用程序的根路径,考虑到全球范围内安装的模块(例如,如果应用程序在运行/var/www/,但模块安装在~/.nvm/v0.x.x/lib/node/)。它不会100%地起作用,但是可以在大多数常见情况下起作用。

优点缺点

在大多数情况下无需配置即可工作。还提供了一些不错的附加便利方法(请参阅项目页面)。最大的缺点是,如果出现以下情况,它将不起作用:

  • 您正在使用启动器,例如pm2
  • AND ,该模块未安装在您应用的node_modules目录中(例如,如果您是全局安装的)

您可以通过设置APP_ROOT_PATH环境变量或调用.setPath()模块来解决此问题,但是在这种情况下,最好使用该global方法。

NODE_PATH环境变量

如果您正在寻找一种 确定
当前应用程序根路径的方法,则上述解决方案之一可能最适合您。另一方面,如果您要解决可靠加载应用程序模块的问题,则强烈建议您调查NODE_PATH环境变量。

Node的模块系统在各种位置查找模块。
这些位置之一是任何process.env.NODE_PATH位置。如果设置此环境变量,则可以require使用标准模块加载器进行模块更改,而无需进行其他任何更改。

例如,如果您将设置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,这就是您的黄金。我将其与我的force-node-
path
模块结合使用,这可以防止意外加载未NODE_PATH设置的应用程序。有关对执行环境变量的更多控制,请参见checkenv

一个陷阱: NODE_PATH 必须 在节点应用程序 外部
设置。您无法执行类似的操作,process.env.NODE_PATH = path.resolve(__dirname)因为模块加载程序会在应用运行之前缓存要搜索的目录列表。

[16年4月6日添加] 另一个试图解决此问题的非常有前途的模块是波浪形的

2020-07-07