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

有没有比process.cwd()更好的方法来确定正在运行的node.js进程的根目录? 就像Rails.root的等价物,但对于Node.js. 我正在寻找尽可能可预测和可靠的事情。

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

require.main.filename

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

当一个文件直接从Node运行时, require.main被设置为它的module 。 这意味着您可以通过testingrequire.main === module来确定文件是否已经直接运行

由于module提供了一个filename属性(通常相当于__filename ),因此可以通过检查require.main.filename来获取当前应用程序的入口点。

所以,如果你想要你的应用程序的基础目录,你可以这样做:

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

优点缺点

这在大多数情况下都能很好地工作,但是如果你使用像pm2这样的启动器运行你的应用程序,或者运行摩卡testing,这个方法将会失败。

global.X

Node有一个名为global全局名称空间对象 – 任何附加到这个对象的东西在你的应用程序的任何地方都是可用的。 所以,在你的index.js (或app.js或任何你的主要应用程序文件被命名),你可以定义一个全局variables:

 // index.js var path = require('path'); global.appRoot = path.resolve(__dirname); // lib/moduleA/component1.js require(appRoot + '/lib/moduleB/component2.js'); 

优点缺点

一致的工作,但你必须依赖一个全局variables,这意味着你不能轻松地重用组件/等。

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 

应用根path

为了解决这个问题,我创build了一个名为app-root-path的节点模块。 用法很简单:

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

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

优点缺点

在大多数情况下不需要configuration。 还提供了一些不错的附加便利方法(请参阅项目页面)。 最大的缺点是,如果:

  • 您正在使用启动器,如pm2
  • 并且 ,该模块不安装在应用程序的node_modules目录中(例如,如果您全局安装它)

你可以通过设置一个APP_ROOT_PATH环境variables或者在模块上调用.setPath()解决这个问题,但是在这种情况下,你最好使用global方法。

NODE_PATH环境variables

如果您正在寻找一种方法来确定当前应用程序的根path,上述解决scheme之一可能对您最有效。 另一方面,如果您试图解决可靠加载应用程序模块的问题,我强烈build议查看NODE_PATH环境variables。

节点的模块系统在各种位置查找模块。 其中一个位置是process.env.NODE_PATH指向的地方 。 如果您设置了这个环境variables,那么您可以使用标准模块加载程序而不需要任何其他更改。

例如,如果您将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来启动你的应用程序,而且你是金手指。 我将它和我的enforce-node-path模块结合起来,这样可以防止在没有设置NODE_PATH情况下意外加载应用程序。 要进一步控制执行环境variables,请参阅checkenv 。

一个问题: NODE_PATH 必须设置在节点应用程序之外。 你不能做类似于process.env.NODE_PATH = path.resolve(__dirname)因为模块加载器会在运行应用程序之前caching它将要search的目录列表。

[另外4/6/16]另一个很有前途的模块试图解决这个问题是波浪式的 。

1-在项目根目录下创build一个文件,将其称为settings.js

在这个文件里面添加这个代码

 module.exports = { POST_MAX_SIZE : 40 , //MB UPLOAD_MAX_FILE_SIZE: 40, //MB PROJECT_DIR : __dirname }; 

3-里面的node_modules创build一个新的模块名称“settings”,在模块里面index.js写下这段代码:

 module.exports = require("../../settings"); 

4-和任何时候你想要你的项目目录只是使用

 var settings = require("settings"); settings.PROJECT_DIR; 

通过这种方式,您将拥有与此文件相关的所有项目目录;)

__dirname不是全局的; 它是当前模块的本地,因此每个文件都有其自己的本地不同的值。

如果你想要正在运行的进程的根目录,你可能想使用process.cwd()

如果您需要可预测性和可靠性,那么您可能需要将其设置为应用程序的某个特定环境variables。 您的应用程序查找MY_APP_HOME (或其他),如果它在那里,并且该应用程序存在于该目录中,则一切正常。 如果它是未定义的或者该目录不包含你的应用程序,那么它应该退出,并提示用户创buildvariables的错误。 它可以被设置为安装过程的一部分。

您可以使用类似于process.env.MY_ENV_VARIABLE东西读取节点中的环境variables。

获取全局根的最简单的方法( 假设你使用NPM来运行你的node.js应用程序“npm start”等

 var appRoot = process.env.PWD; 

如果你想交叉validation上述

假设您想用node.js应用程序的设置来交叉检查process.env.PWD 。 如果你想要一些运行时testing来检查process.env.PWD的有效性,你可以用这个代码(我写的看起来工作的很好)进行交叉检查。 您可以使用package.json文件中的npm_package_name来交叉检查appRoot中最后一个文件夹的名称,例如:

  var path = require('path'); var globalRoot = __dirname; //(you may have to do some substring processing if the first script you run is not in the project root, since __dirname refers to the directory that the file is in for which __dirname is called in.) //compare the last directory in the globalRoot path to the name of the project in your package.json file var folders = globalRoot.split(path.sep); var packageName = folders[folders.length-1]; var pwd = process.env.PWD; var npmPackageName = process.env.npm_package_name; if(packageName !== npmPackageName){ throw new Error('Failed check for runtime string equality between globalRoot-bottommost directory and npm_package_name.'); } if(globalRoot !== pwd){ throw new Error('Failed check for runtime string equality between globalRoot and process.env.PWD.'); } 

你也可以使用这个NPM模块: require('app-root-path') ,这对于这个目的非常有效

也许你可以尝试从__filename向上遍历,直到find一个package.json ,并决定这是你当前文件所属的主目录。

所有这些“根目录”大多需要解决一些虚拟path到一个真正的path,所以可能你应该看看path.resolve

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

即使从子文件夹中调用应用程序,我仍然发现这一切对我来说都是一致的,因为它可以使用一些testing框架,如Mocha:

 process.mainModule.paths[0].split('node_modules')[0].slice(0, -1); 

为什么它的作品:

运行时节点创build所有加载文件的完整path的registry。 模块首先被加载,因此在这个registry的顶部。 通过selectregistry的第一个元素并返回“node_modules”目录之前的path,我们可以确定应用程序的根目录。

这只是一行代码,但为了简单起见(我的意思),我把黑盒子装进了一个NPM模块:

https://www.npmjs.com/package/node-root.pddivine

请享用!

实际上,我发现也许最简单的解决scheme也是最强大的:只需将以下文件放在项目的根目录下:root-path.js,它具有以下代码:

import * as path from 'path' const projectRootPath = path.resolve(__dirname) export const rootPath = projectRootPath

我发现在使用express时有用的技术是在设置任何其他路由之前将以下内容添加到app.js中

 // set rootPath app.use(function(req, res, next) { req.rootPath = __dirname; next(); }); app.use('/myroute', myRoute); 

不需要使用全局variables,并且将根目录的path作为请求对象的属性。

如果你的app.js在你的项目的根目录下,默认情况下是这样的。

我用这个

对于我的模块名为mymodule

var BASE_DIR = __dirname.replace(/^(.*\/mymodule)(.*)$/, '$1')

在app.js中创build一个函数

/*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')); 

在主文件的顶部添加:

 mainDir = __dirname; 

然后在你需要的任何文件中使用它:

 console.log('mainDir ' + mainDir); 
  • mainDir是全局定义的,如果您只需要在当前文件中使用它,请改用__dirname
  • 主文件通常位于项目的根文件夹中,并被命名为main.jsindex.jsgulpfile.js

获取当前文件的path名称:

在该文件中定义:


     var get_stack = function(){
         var orig = Error.prepareStackTrace;
         Error.prepareStackTrace = function(_,stack){
            返回堆栈;
         };
         var err = new Error;
         Error.captureStackTrace(err,arguments.callee);
         var stack = err.stack;
         Error.prepareStackTrace = orig;
        返回堆栈;
     };

该文件中的用法:


    的console.log(get_stack()[0] .getFileName());

API:
堆栈跟踪

尝试path._makeLong('some_filename_on_root.js');

例:

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

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