除了process.cwd()之外,是否有其他方法来获取当前项目根目录的路径名。Node是否实现了ruby的属性Rails.root之类的东西。我要找的是稳定可靠的东西。


当前回答

你也可以使用 Git rev-parse——show- topllevel 假设您正在使用git存储库

其他回答

所有这些“根dirs”大多需要解析一些虚拟路径到一个真实的堆路径,所以可能你应该看看path.resolve?

var path= require('path');
var filePath = path.resolve('our/virtual/path.ext');

解决这个问题有很多种方法,每种方法都有其优缺点:

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]另一个非常有前途的模块,试图解决这个问题是波浪。

尝试path._makeLong(“some_filename_on_root.js”);

例子:

cons path = require('path');
console.log(path._makeLong('some_filename_on_root.js');

这将返回你的节点应用程序的根目录的完整路径(与package.json相同的位置)

你也可以使用 Git rev-parse——show- topllevel 假设您正在使用git存储库

找到电子应用程序的根路径可能会很棘手。因为在不同的条件下,例如生产、开发和打包条件下,主进程和渲染器的根路径是不同的。

我写了一个npm包electronic -root-path来捕获电子应用程序的根路径。

$ npm install electron-root-path

or 

$ yarn add electron-root-path


// Import ES6 way
import { rootPath } from 'electron-root-path';

// Import ES2015 way
const rootPath = require('electron-root-path').rootPath;

// e.g:
// read a file in the root
const location = path.join(rootPath, 'package.json');
const pkgInfo = fs.readFileSync(location, { encoding: 'utf8' });