Determine project root from a running node.js application
是否有比
有几种方法可以解决这个问题,每种方法各有利弊:
require.main.filename
来自http://nodejs.org/api/modules.html:
When a file is run directly from Node,
require.main is set to itsmodule . That means that you can determine whether a file has been run directly by testingrequire.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 .
因此,如果您想要应用程序的基本目录,您可以执行以下操作:
1 2 | var path = require('path'); var appDir = path.dirname(require.main.filename); |
优点缺点
这在大多数情况下都会很好用,但如果您使用像pm2这样的启动器运行应用程序或运行mocha测试,则此方法将失败。
global.X
Node有一个名为
1 2 3 4 5 6 | // index.js var path = require('path'); global.appRoot = path.resolve(__dirname); // lib/moduleA/component1.js require(appRoot + '/lib/moduleB/component2.js'); |
优点缺点
一致地工作,但你必须依赖一个全局变量,这意味着你不能轻易地重用组件/等。
process.cwd()
这将返回当前工作目录。根本不可靠,因为它完全取决于启动进程的目录:
1 2 3 4 5 6 7 8 | $ 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的节点模块。用法很简单:
1 2 | var appRoot = require('app-root-path'); var myModule = require(appRoot + '/lib/my-module.js'); |
app-root-path模块使用几种不同的技术来确定应用程序的根路径,同时考虑全局安装的模块(例如,如果您的应用程序在
优点缺点
大多数情况下无需配置即可工作还提供了一些不错的额外便利方法(参见项目页面)。最大的问题是,如果:
- 你正在使用像pm2这样的启动器
-
并且,模块未安装在应用程序的
node_modules 目录中(例如,如果您全局安装)
您可以通过设置
NODE_PATH环境变量
如果您正在寻找确定当前应用程序根路径的方法,则上述解决方案之一可能最适合您。另一方面,如果您正在尝试可靠地解决加载应用模块的问题,我强烈建议您查看
Node的模块系统在各种位置查找模块。其中一个位置是
例如,如果将
1 2 | require('module2/component.js'); // ^ looks for /var/www/lib/module2/component.js |
一个很好的方法是使用
1 2 3 | "scripts": { "start":"NODE_PATH=. node app.js" } |
现在你可以用
一个问题:
[16/6/16添加]试图解决这个问题的另一个非常有前途的模块是波浪状的。
如果您想要正在运行的进程的根目录,则可能需要使用
如果您想要可预测性和可靠性,那么您可能需要将应用程序的要求设置为某个环境变量。你的应用程序寻找
您可以使用类似
1-在项目根目录中创建一个文件,调用它settings.js
2-在此文件中添加此代码
1 2 3 4 5 | module.exports = { POST_MAX_SIZE : 40 , //MB UPLOAD_MAX_FILE_SIZE: 40, //MB PROJECT_DIR : __dirname }; |
3-在node_modules里面创建一个新的模块名称"settings"并在模块index.js里面写下这段代码:
1 | module.exports = require("../../settings"); |
4-以及您希望项目目录使用的任何时间
1 2 | var settings = require("settings"); settings.PROJECT_DIR; |
通过这种方式,您将拥有与此文件相关的所有项目目录;)
获取全局根的最简单方法(假设你使用NPM运行你的node.js app'npm start'等)
1 | var appRoot = process.env.PWD; |
如果你想交叉验证上面的内容
假设您要使用node.js应用程序的设置交叉检查
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | 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模块:
我发现这对我来说一直都有效,即使从子文件夹调用应用程序,因为它可以与一些测试框架一样,如Mocha:
1 | process.mainModule.paths[0].split('node_modules')[0].slice(0, -1); |
为什么会这样:
在运行时节点创建所有已加载文件的完整路径的注册表。模块首先加载,因此位于此注册表的顶部。通过选择注册表的第一个元素并在'node_modules'目录之前返回路径,我们可以确定应用程序的根目录。
它只是一行代码,但为了简单起见(我的缘故),我把它装入一个NPM模块:
https://www.npmjs.com/package/node-root.pddivine
请享用!
所有这些"根目录"主要需要解决一些虚拟路径到一个真正的桩路径,所以你应该看看
1 2 | var path= require('path'); var filePath = path.resolve('our/virtual/path.ext"); |
也许您可以尝试从
实际上,我发现也许最简单的解决方案也是最强大的:
您只需将以下文件放在项目的根目录:root-path.js,其中包含以下代码:
1 2 3 | import * as path from 'path' const projectRootPath = path.resolve(__dirname) export const rootPath = projectRootPath |
我在使用express时发现有用的技术是在设置任何其他路由之前将以下内容添加到app.js
1 2 3 4 5 6 7 | // set rootPath app.use(function(req, res, next) { req.rootPath = __dirname; next(); }); app.use('/myroute', myRoute); |
无需使用全局变量,并且您将根目录的路径作为请求对象的属性。
如果您的app.js位于项目的根目录中,默认情况下,这是有效的。
我知道这个已经太晚了。
但我们可以通过两种方法获取根URL
第一种方法
1 2 | var path = require('path'); path.dirname(require.main.filename); |
第二种方法
1 2 | var path = require('path'); path.dirname(process.mainModule.filename); |
参考链接: - https://gist.github.com/geekiam/e2e3e0325abd9023d3a3
让它变得性感????
1 2 3 4 | const users = require('../../../database/users'); // ?? what you have // OR const users = require('$db/users'); // ?? no matter how deep you are const products = require('/database/products'); // ?? alias or pathing from root directory |
解决丑陋道路问题的三个简单步骤。
在主应用程序文件的顶部包含一次
1 2 3 4 | require('sexy-require'); const routers = require('/routers'); const api = require('$api'); ... |
可选步骤。路径配置可以在项目根目录的
1 2 3 | $db = /server/database $api-v1 = /server/api/legacy $api-v2 = /server/api/v2 |
在主文件顶部添加:
1 | mainDir = __dirname; |
然后在您需要的任何文件中使用它:
1 | console.log('mainDir ' + mainDir); |
-
mainDir 是全局定义的,如果只在当前文件中需要它 - 请改用__dirname 。 -
主文件通常位于项目的根文件夹中,并命名为
main.js ,index.js ,gulpfile.js 。
将其添加到主应用程序文件的开头(例如app.js):
1 | global.__basedir = __dirname; |
这将设置一个全局变量,该变量将始终等于应用程序的基础目录。像任何其他变量一样使用它:
1 | const yourModule = require(__basedir + '/path/to/module.js'); |
简单...
就像在root中将此行添加到模块一样简单,通常是app.js
1 | global.__basedir = __dirname; |
然后_basedir将可以访问您的所有模块。
我用这个。
对于名为
1 2 3 | process.mainModule.paths .filter(p => !p.includes('node_modules')) .shift() |
获取主模块中的所有路径并过滤掉那些带有"node_modules"的路径,
然后获得剩余路径列表的第一个。意外行为不会抛出错误,只是
对我来说效果很好,即使在调用ie
您只需在express app变量中添加根目录路径,然后从应用程序中获取此路径。为此,在index.js或app.js文件中添加
老问题,我知道,然而毫无疑问提到使用
这不是一个你可以直接使用的例子(因为使用我自己的框架),但我认为它可以让你知道如何做到这一点。我还使用缓存方法来避免调用此函数对系统造成太大压力,尤其是在未指定扩展时(并且需要检查文件),例如:
1 | node myfile |
要么
1 | node myfile.js |
这就是我缓存它的原因,另请参阅下面的代码。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 | function getRootFilePath() { if( !isDefined( oData.SU_ROOT_FILE_PATH ) ) { var sExt = false; each( process.argv, function( i, v ) { // Skip invalid and provided command line options if( !!v && isValidString( v ) && v[0] !== '-' ) { sExt = getFileExt( v ); if( ( sExt === 'js' ) || ( sExt === '' && fileExists( v+'.js' )) ) { var a = uniformPath( v ).split("/"); // Chop off last string, filename a[a.length-1]=''; // Cache it so we don't have to do it again. oData.SU_ROOT_FILE_PATH=a.join("/"); // Found, skip loop return true; } } }, true ); // <-- true is: each in reverse order } return oData.SU_ROOT_FILE_PATH || ''; } }; |
在app.js中创建一个函数
1 2 3 4 5 6 7 8 9 | 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')); |
找到电子应用程序的根路径可能会变得棘手。因为主进程和渲染器的根路径在不同的条件下是不同的,例如生产,开发和打包条件。
我编写了一个npm包电子根路径来捕获电子应用程序的根路径。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | $ 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' }); |
试试
例:
1 2 | cons path = require('path'); console.log(path._makeLong('some_filename_on_root.js'); |
这将从您的节点应用程序的根返回完整路径(package.json的相同位置)
只需使用:
1 | path.resolve("./") ... output is your project root directory |
__dirname将为您提供根目录,只要您位于根目录中的文件中即可。
1 2 3 4 5 6 7 | // ProjectDirectory.js (this file is in the project's root directory because you are putting it there). module.exports = { root() { return __dirname; } } |
在其他一些文件中:
1 2 | const ProjectDirectory = require('path/to/ProjectDirectory'); console.log(`Project root directory is ${ProjectDirectory.root}`); |