本文翻译自:Determine project root from a running node.js application
Is there a better way than process.cwd()
to determine the root directory of a running node.js process? 有没有比process.cwd()
更好的方法来确定正在运行的node.js进程的根目录? Something like the equivalent of Rails.root
, but for Node.js. 类似于Rails.root
,但适用于Node.js。 I'm looking for something that is as predictable and reliable as possible. 我正在寻找尽可能可预测和可靠的东西。
参考:https://stackoom.com/question/H4Bo/从运行的node-js应用程序确定项目根目录
__dirname
isn't a global; __dirname
不是全局的; it's local to the current module so each file has its own local, different value. 它在当前模块本地,因此每个文件都有其自己的本地值。
If you want the root directory of the running process, you probably do want to use process.cwd()
. 如果要运行的进程的根目录,则可能确实要使用process.cwd()
。
If you want predictability and reliability, then you probably need to make it a requirement of your application that a certain environment variable is set. 如果需要可预测性和可靠性,则可能需要使您的应用程序要求设置某个环境变量。 Your app looks for MY_APP_HOME
(Or whatever) and if it's there, and the application exists in that directory then all is well. 您的应用程序查找MY_APP_HOME
(或其他),如果存在,并且该应用程序存在于该目录中,则一切正常。 If it is undefined or the directory doesn't contain your application then it should exit with an error prompting the user to create the variable. 如果未定义或目录不包含您的应用程序,则它应退出并出现错误提示用户创建变量。 It could be set as a part of an install process. 可以将其设置为安装过程的一部分。
You can read environment variables in node with something like process.env.MY_ENV_VARIABLE
. 您可以使用诸如process.env.MY_ENV_VARIABLE
类的内容读取节点中的环境变量。
1- create a file in the project root call it settings.js 1-在项目根目录中创建一个文件,将其称为settings.js
2- inside this file add this code 2-在此文件中添加此代码
module.exports = {
POST_MAX_SIZE : 40 , //MB
UPLOAD_MAX_FILE_SIZE: 40, //MB
PROJECT_DIR : __dirname
};
3- inside node_modules create a new module name it "settings" and inside the module index.js write this code: 3-在node_modules内部创建一个新的模块名称,即“设置”,并在模块index.js内部编写以下代码:
module.exports = require("../../settings");
4- and any time you want your project directory just use 4-以及您希望项目目录仅使用的任何时间
var settings = require("settings");
settings.PROJECT_DIR;
in this way you will have all project directories relative to this file ;) 这样,您将拥有与此文件相关的所有项目目录;)
There are several ways to approach this, each with their own pros and cons: 有几种方法可以解决此问题,每种方法各有利弊:
From http://nodejs.org/api/modules.html : 来自http://nodejs.org/api/modules.html :
When a file is run directly from Node,
require.main
is set to itsmodule
. 直接从Node运行文件时,将require.main
设置为其module
。 That means that you can determine whether a file has been run directly by testingrequire.main === module
这意味着您可以通过测试require.main === module
来确定文件是否已直接运行。Because
module
provides afilename
property (normally equivalent to__filename
), the entry point of the current application can be obtained by checkingrequire.main.filename
. 由于module
提供了filename
属性(通常等效于__filename
),因此可以通过检查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);
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. 在大多数情况下,这会很好用,但是如果您使用pm2之类的启动器运行应用程序或运行mocha测试,则此方法将失败。
Node has aa global namespace object called global
— anything that you attach to this object will be available everywhere in your app. 节点有一个名为global
全局命名空间对象-您附加到此对象的所有对象都将在您的应用程序中随处可用。 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
(或app.js
或主应用程序文件中的任何名称)中,您可以定义一个全局变量:
// index.js
var path = require('path');
global.appRoot = path.resolve(__dirname);
// lib/moduleA/component1.js
require(appRoot + '/lib/moduleB/component2.js');
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
To address this issue, I've created a node module called app-root-path . 为了解决这个问题,我创建了一个名为app-root-path的节点模块。 Usage is simple: 用法很简单:
var appRoot = require('app-root-path');
var myModule = require(appRoot + '/lib/my-module.js');
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.xx/lib/node/
). app-root-path模块使用几种不同的技术来确定应用程序的根路径,同时考虑到全局安装的模块(例如,如果您的应用程序在/var/www/
运行,但该模块在~/.nvm/v0.xx/lib/node/
安装) ~/.nvm/v0.xx/lib/node/
)。 It won't work 100% of the time, but it's going to work in most common scenarios. 它不会100%地起作用,但是可以在大多数常见情况下起作用。
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: 最大的缺点是,如果出现以下情况,它将不起作用:
node_modules
directory (for example, if you installed it globally) AND ,该模块未安装在您应用的node_modules
目录中(例如,如果您是全局安装的) 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. 您可以通过设置APP_ROOT_PATH
环境变量或在模块上调用.setPath()
解决此问题,但在这种情况下,最好使用global
方法。
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_PATH
环境变量。
Node's Modules system looks for modules in a variety of locations. Node的模块系统在各种位置查找模块。 One of these locations is wherever process.env.NODE_PATH
points . 这些位置之一是process.env.NODE_PATH
指向的位置 。 If you set this environmental variable, then you can require
modules with the standard module loader without any other changes. 如果设置此环境变量,则可以require
具有标准模块加载器的模块,而无需进行任何其他更改。
For example, if you set NODE_PATH
to /var/www/lib
, the the following would work just fine: 例如,如果将NODE_PATH
设置为/var/www/lib
,则可以很好地进行以下操作:
require('module2/component.js');
// ^ looks for /var/www/lib/module2/component.js
A great way to do this is using npm
: 一个很好的方法是使用npm
:
"scripts": {
"start": "NODE_PATH=. node app.js"
}
Now you can start your app with npm start
and you're golden. 现在,您可以使用npm start
来启动您的应用程序了,您就很高兴。 I combine this with my enforce-node-path module, which prevents accidentally loading the app without NODE_PATH
set. 我将其与我的NODE_PATH
-node-path模块结合使用,这可以防止在未设置NODE_PATH
情况下意外加载应用程序。 For even more control over enforcing environmental variables, see checkenv . 有关对执行环境变量的更多控制,请参见checkenv 。
One gotcha: NODE_PATH
must be set outside of the node app. 一个 NODE_PATH
: 必须在节点应用程序外部设置NODE_PATH
。 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. 您无法执行类似process.env.NODE_PATH = path.resolve(__dirname)
因为模块加载程序会在应用程序运行之前缓存将搜索的目录列表。
[added 4/6/16] Another really promising module that attempts to solve this problem is wavy . [16年4月6日添加]试图解决此问题的另一个非常有前途的模块是波浪形的 。
All these "root dirs" mostly need to resolve some virtual path to a real pile path, so may be you should look at path.resolve
? 所有这些“根目录”都需要将一些虚拟路径解析为真实的堆路径,因此您可能应该看看path.resolve
?
var path= require('path');
var filePath = path.resolve('our/virtual/path.ext");
Create a function in app.js 在app.js中创建一个函数
/*Function to get the app root folder*/
var appRootFolder = function(dir,level){
var arr = dir.split('\\');
arr.splice(arr.length - level,level);
var rootFolder = arr.join('\\');
return rootFolder;
}
// view engine setup
app.set('views', path.join(appRootFolder(__dirname,1),'views'));