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

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

问题描述

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

Is there a better way than process.cwd() to determine the root directory of a running node.js process? Something like the equivalent of Rails.root, but for Node.js. I'm looking for something that is as predictable and reliable as possible.

推荐答案

有几种解决方法,每种方法各有利弊:

There are several 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:

var path = require('path');
var appDir = path.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有一个名为global的全局命名空间对象-您附加到此对象的任何内容都将在您的应用程序中随处可见.因此,在您的index.js(或app.js或您的主应用程序文件中的任何名称)中,您只需定义一个全局变量即可:

Node has a 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-root-path

为解决此问题,我创建了一个名为 app-的节点模块根路径 .用法很简单:

app-root-path

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

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

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

The app-root-path module uses several different 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.

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

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

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

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