実行中のnode.jsアプリケーションからプロジェクトルートを決定する

実行中のnode.jsプロセスのルートディレクトリを決定するのに、process.cwd()より良い方法はありますか?Rails.root`に相当するようなもので、Node.js用のものです。できるだけ予測可能で信頼できるものを探しています。

質問へのコメント (2)
ソリューション

これにはいくつかの方法があり、それぞれに長所と短所がある:

require.main.filename

from:

ファイルがNodeから直接実行されると、require.mainはそのmoduleに設定される。つまり、ファイルが直接実行されたかどうかは require.main === module をテストすることで判断できます。 をテストすることでファイルが直接実行されたかどうかを判断できる; モジュールfilenameプロパティ(通常は__filenameと等価)を提供するので、require.main.filename` をチェックすることで、現在のアプリケーションのエントリポイントを得ることができる。

そのため、アプリのベースディレクトリが必要な場合は、次のようにすることができる:

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

長所と短所

これはほとんどの場合うまくいきますが、pm2 のようなランチャーでアプリを実行していたり、mocha テストを実行していたりすると、この方法は失敗します。

global.X

Node には global というグローバル名前空間オブジェクトがあります。 つまり、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');

長所と短所

一貫して動作するが、グローバル変数に依存しなければならない。

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

app-root-path

この問題に対処するために、app-root-pathというnodeモジュールを作成しました。 使い方は簡単です:

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

app-root-path](https://github.com/inxilpro/node-app-root-path)**モジュールは、グローバルにインストールされたモジュール(例えば、アプリが /var/www/ で実行されているが、モジュールが ~/.nvm/v0.x.x/lib/node/ にインストールされている場合)を考慮して、アプリのルートパスを決定するためにいくつかの異なるテクニックを使用します。 100%常にうまくいくわけではありませんが、一般的なシナリオではうまくいくでしょう。

長所と短所

ほとんどの場合、設定なしで動作する。 また、いくつかの便利な追加メソッドも提供する(プロジェクトページを参照)。 最大の欠点は、以下の場合には動作しないことである:

  • pm2のようなランチャーを使っている場合。
  • モジュールがアプリの node_modules ディレクトリにインストールされていない場合。

環境変数 APP_ROOT_PATH を設定するか、モジュールに対して .setPath() を呼び出すことで回避できますが、その場合は global メソッドを使用した方が良いでしょう。

NODE_PATH 環境変数

もし、現在のアプリのルートパスを決定する方法を探しているのであれば、上記の解決方法のいずれかが最適でしょう。 一方、アプリモジュールを確実にロードする問題を解決したいのであれば、環境変数 NODE_PATH を調べることを強くお勧めします。

NodeのModules systemは様々な場所でモジュールを探します。 これらの場所の1つは、process.env.NODE_PATHが指す場所です。この環境変数を設定すると、他の変更なしに標準のモジュールローダーでモジュールを require することができます。

例えば、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が設定されていない状態でアプリをロードしてしまうのを防いでいる。環境変数をさらにコントロールしたい場合は、checkenv を参照してください。

One gotcha: NODE_PATH must be set outside of the node app. なぜなら、モジュール・ローダーがアプリの実行前に検索するディレクトリのリストをキャッシュするからです。

**この問題を解決しようとするもう一つの有望なモジュールがwavyだ。

解説 (22)

dirname`はグローバルなものではなく、現在のモジュールにローカルなものである。

実行中のプロセスのルート・ディレクトリが必要な場合は、process.cwd()を使うことになるだろう。

予測可能性と信頼性を求めるのであれば、特定の環境変数が設定されていることをアプリケーションの要件にする必要があるだろう。アプリはMY_APP_HOME(または何でもいい)を探し、もしそれがあり、アプリケーションがそのディレクトリに存在すれば、すべてうまくいく。もしそれが未定義であったり、そのディレクトリにアプリケーションがなかったりすれば、ユーザーに変数を作成するよう促すエラーとともに終了するはずです。インストール・プロセスの一部として設定することもできます。

nodeの環境変数はprocess.env.MY_ENV_VARIABLEのようなもので読み込むことができる。

解説 (2)

1- プロジェクトのルートにsettings.jsというファイルを作成する。

2- このファイルに次のコードを追加する

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

3- node_modulesの中に新しいモジュールを作成し、名前を "settings"とし、そのモジュールindex.jsの中に次のコードを記述する:

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

4- そして、いつでもプロジェクト・ディレクトリに

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

こうすることで、すべてのプロジェクト・ディレクトリがこのファイルからの相対パスになります;)

解説 (9)

グローバルルートを取得する最も簡単な方法( NPMを使用してnode.jsアプリの「npm start」を実行するとします)。

var appRoot = process.env.PWD;

上記を相互検証したい場合

process.env.PWDをnode.jsアプリケーションの設定と照合するとします。 ランタイムテストで「process.env.PWD」の有効性を確認したい場合は、このコード(私が書いたものでうまく機能しているようです)と照合できます。 appRootの最後のフォルダーの名前を、package.jsonファイルのnpm_package_nameとクロスチェックできます。例:

    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')は、この目的に非常にうまく機能します。

解説 (4)

これは、アプリケーションがサブフォルダーから呼び出された場合でも、Mocha :などのいくつかのテストフレームワークと同様に、一貫して機能することを発見しました。

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

それが機能する理由:

実行時に、ノードはすべてのロードされたファイルのフルパスのレジストリを作成します。 モジュールは最初にロードされるため、このレジストリの上部にあります。 レジストリの最初の要素を選択し、「node_modules」ディレクトリの前のパスを返すことにより、アプリケーションのルートを決定できます。

これは1行のコードですが、簡単にするために(私のために)、NPMモジュールにブラックボックス化しました。

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

楽しい。!

解説 (1)

__filenameから package.jsonが見つかるまで上向きにトラバースして、それが現在のファイルが属するメインディレクトリであると判断できるかもしれません。

解説 (0)

これらのすべての「ルートディル」は、実際のパイルパスへの仮想パスを解決する必要があるため、「path.resolve」を確認する必要があります?

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

実際、私はおそらく最も堅 ⁇ な解決策も見つけます。 プロジェクトのルートディレクトリに次のファイルを配置するだけです。次のコードを持つroot-path.js:

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

この行をルートのモジュールに追加するのと同じくらい簡単です。通常はapp.jsです。

global.__basedir = __dirname;

次に、_basedirはすべてのモジュールにアクセスできます。

解説 (0)

expressを使用するときに役立つと思われる手法は、他のルートを設定する前に、app.jsに以下を追加することです。

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

app.use('/myroute', myRoute);

globalsを使用する必要はなく、リクエストオブジェクトのプロパティとしてルートディレクトリのパスを持っています。

これは、app.jsがプロジェクトのルートにある場合に機能します。デフォルトでは、ルートです。

解説 (0)

これはもう手遅れです。 ただし、ルートURLを2つの方法でフェッチできます。

1番目の方法。

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

2番目の方法。

var path = require('path');
path.dirname(process.mainModule.filename);

参照リンク:-https://gist.github.com/geekiam/e2e3e0325abd9023d3a3

解説 (0)

セクシーにする💃🏻 .< br />。

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
< br />。

醜い道の問題を解決するための3つの簡単なステップ。

1。 パッケージをインストール: npm install sexy-require --save< br />。 2。 メインアプリケーションファイルの上部に「require( 'sexy-require')」を1回含めます。

    require( 'sexy-require');。
    const routers = require( '/ routers');。
    const api = require( '$ api');。
    ...

3。 オプションのステップ。 パス構成は、プロジェクトのルートディレクトリの「.paths」ファイルで定義できます。

    $ db = / server / database。
    $ api-v1 = / server / api / legacy。
    $ api-v2 = / server / api / v2。
解説 (2)

メインファイルの上部に以下を追加します。

mainDir = __dirname;

次に、必要なファイルで使用します。

console.log('mainDir ' + mainDir);
  • mainDirはグローバルに定義されます。現在のファイルでのみ必要な場合は、代わりに __dirnameを使用します。 *メインファイルは通常、プロジェクトのルートフォルダにあり、「main.js」、「index.js」、「gulpfile.js」のように名前が付けられます。
解説 (0)

これを使います。

「mymodule」という名前の私のモジュール。

var BASE_DIR = __dirname.replace(/ ^(。* \ / mymodule)(。*)$ /、「$ 1」)

解説 (0)

これをメインアプリファイルの先頭に追加します(例:. app.js):

global.__basedir = __dirname;

これにより、常にアプリのベースディレクトリと同等のグローバル変数が設定されます。 他の変数と同じように使用します。

const yourModule = require(__basedir + '/path/to/module.js');

シンプル。..

解説 (0)

process.envINIT_CWDプロパティがあります。 これは、現在プロジェクトで取り組んでいることです。

const {INIT_CWD} = process.env; // process.env.INIT_CWD 
const paths = require(`${INIT_CWD}/config/paths`);

幸運を。..

解説 (2)

express app変数にルートディレクトリパスを追加して、このパスをアプリから取得するだけです。 これには、index.jsまたはapp.jsファイルに app.set( 'rootDirectory'、__dirname);を追加します。 また、コードのルートディレクトリパスを取得するには、 req.app.get( 'rootDirectory')を使用します。

解説 (0)

実行中のnode.jsアプリケーションからプロジェクトルートを決定する場合は、単純にも可能です。 。 process.mainModule.path。

解説 (0)

これで十分です。

path.join(...process.argv[1].split(/\/|\\/).slice(0, -1))
解説 (0)
process.mainModule.paths
  .filter(p => !p.includes('node_modules'))
  .shift()

メインモジュールのすべてのパスを取得し、「node_modules」でそれらを除外します。 次に、残りの最初のパスリストを取得します。 予期しない動作はエラーをスローせず、単に「未定義」です。

ie $ mochaを呼び出すときでも、私にとってはうまくいきます。

解説 (0)