从正在运行的 node.js 应用程序确定项目根目录 [英] Determine project root from a running node.js application

查看:30
本文介绍了从正在运行的 node.js 应用程序确定项目根目录的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

Is there a different way, other than process.cwd(), to get the pathname of the current project's root-directory. Does Node implement something like ruby's property, Rails.root,. I'm looking for something that is constant, and reliable.

推荐答案

有很多方法可以解决这个问题,每种方法都有自己的优缺点:

There are many ways to approach this, each with their own pros and cons:

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

当一个文件直接从 Node 运行时,require.main 被设置为它的 module.这意味着您可以通过测试 require.main === module

When a file is run directly from Node, require.main is set to its module. That means that you can determine whether a file has been run directly by testing require.main === module

由于module提供了一个filename属性(一般相当于__filename),可以通过勾选<代码>require.main.filename.

Because module provides a filename property (normally equivalent to __filename), the entry point of the current application can be obtained by checking require.main.filename.

因此,如果您想要应用程序的基本目录,您可以这样做:

So if you want the base directory for your app, you can do:

const { dirname } = require('path');
const appDir = dirname(require.main.filename);

优点 &缺点

这在大多数情况下都很好用,但如果您使用 pm2 之类的启动器运行应用程序或运行 mocha 测试,则此方法将失败.

Pros & Cons

This will work great most of the time, but if you're running your app with a launcher like pm2 or running mocha tests, this method will fail.

Node 将所有模块搜索路径发布到 module.paths.我们可以遍历这些并选择第一个解析的.

Node publishes all the module search paths to module.paths. We can traverse these and pick the first one that resolves.

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
    }
  }
}

优点 &缺点

这有时会起作用,但在包中使用时并不可靠,因为它可能返回安装包的目录,而不是安装应用程序的目录.

Pros & Cons

This will sometimes work, but is not reliable when used in a package because it may return the directory that the package is installed in rather than the directory that the application is installed in.

Node 有一个名为 global 的全局命名空间对象——你附加到这个对象的任何东西都可以在你的应用程序的任何地方使用.因此,在您的 index.js (或 app.js 或任何您的主应用程序中文件被命名),你可以定义一个全局变量:

Node has a global namespace object called global — anything that you attach to this object will be available everywhere in your app. So, in your index.js (or app.js or whatever your main app file is named), you can just define a global variable:

// index.js
var path = require('path');
global.appRoot = path.resolve(__dirname);

// lib/moduleA/component1.js
require(appRoot + '/lib/moduleB/component2.js');

优点 &缺点

始终如一地工作,但您必须依赖全局变量,这意味着您无法轻松重用组件/等.

Pros & Cons

Works consistently, but you have to rely on a global variable, which means that you can't easily reuse components/etc.

这将返回当前工作目录.根本不可靠,因为它完全取决于进程是从哪个目录启动的:

This returns the current working directory. Not reliable at all, as it's entirely dependent on what directory the process was launched from:

$ 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- 的节点模块根路径.用法很简单:

app-root-path

To address this issue, I've created a node module called app-root-path. Usage is simple:

const appRoot = require('app-root-path');
const myModule = require(`${ appRoot }/lib/my-module.js`);

app-root-path 模块使用多种技术来确定应用程序的根路径,同时考虑到全局安装的模块(例如,如果您的应用程序在 /var/www/ 中运行但模块安装在 ~/.nvm/v0.xx/lib/node/).它不会在 100% 的时间里工作,但它会在最常见的情况下工作.

The app-root-path module uses several techniques to determine the root path of the app, taking into account globally installed modules (for example, if your app is running in /var/www/ but the module is installed in ~/.nvm/v0.x.x/lib/node/). It won't work 100% of the time, but it's going to work in most common scenarios.

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

Works without configuration in most circumstances. Also provides some nice additional convenience methods (see project page). The biggest con is that it won't work if:

  • 您正在使用启动器,例如 pm2
  • AND,该模块未安装在您应用的 node_modules 目录中(例如,如果您全局安装)
  • You're using a launcher, like pm2
  • AND, the module isn't installed inside your app's node_modules directory (for example, if you installed it globally)

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

You can get around this by either setting a APP_ROOT_PATH environmental variable, or by calling .setPath() on the module, but in that case, you're probably better off using the global method.

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

If you're looking for a way to determine the root path of the current app, one of the above solutions is likely to work best for you. If, on the other hand, you're trying to solve the problem of loading app modules reliably, I highly recommend looking into the NODE_PATH environmental variable.

Node 的 模块系统 在各种位置查找模块.这些位置之一是 process.env.NODE_PATH 指向的任何地方.如果你设置了这个环境变量,那么你可以使用标准模块加载器require模块,而无需任何其他更改.

Node's Modules system looks for modules in a variety of locations. One of these locations is wherever process.env.NODE_PATH points. If you set this environmental variable, then you can require modules with the standard module loader without any other changes.

例如,如果您将 NODE_PATH 设置为 /var/www/lib,则以下内容可以正常工作:

For example, if you set NODE_PATH to /var/www/lib, the the following would work just fine:

require('module2/component.js');
// ^ looks for /var/www/lib/module2/component.js

一个很好的方法是使用 npm:

A great way to do this is using npm:

{
  "scripts": {
    "start": "NODE_PATH=. node app.js"
  }
}

现在您可以使用 npm start 启动您的应用程序,您就可以了.我将它与我的 enforce-node-path 模块结合使用,这样可以防止意外加载应用程序而没有NODE_PATH 设置.如需对执行环境变量的更多控制,请参阅 checkenv.

Now you can start your app with npm start and you're golden. I combine this with my enforce-node-path module, which prevents accidentally loading the app without NODE_PATH set. For even more control over enforcing environmental variables, see checkenv.

一个问题: NODE_PATH 必须设置在节点应用的外部.您不能执行 process.env.NODE_PATH = path.resolve(__dirname) 之类的操作,因为模块加载器会在您的应用程序运行之前缓存它将搜索的目录列表.

One gotcha: NODE_PATH must be set outside of the node app. You cannot do something like process.env.NODE_PATH = path.resolve(__dirname) because the module loader caches the list of directories it will search before your app runs.

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

[added 4/6/16] Another really promising module that attempts to solve this problem is wavy.

这篇关于从正在运行的 node.js 应用程序确定项目根目录的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆