以外process.cwd()
に、現在のプロジェクトのルート ディレクトリのパス名を取得する別の方法はありますか。Node は ruby のプロパティのようなものを実装していますかRails.root
? 一定で信頼できるものを探しています。
32 に答える
これには多くの方法があり、それぞれに長所と短所があります。
require.main.filename
http://nodejs.org/api/modules.htmlから:
ファイルがノードから直接実行
require.main
されると、そのmodule
. つまり、テストによってファイルが直接実行されたかどうかを判断できます。require.main === module
module
はfilename
プロパティ (通常は と同等) を提供するため__filename
、現在のアプリケーションのエントリ ポイントは をチェックすることで取得できますrequire.main.filename
。
したがって、アプリのベース ディレクトリが必要な場合は、次のようにします。
const { dirname } = require('path');
const appDir = dirname(require.main.filename);
長所短所
これはほとんどの場合うまく機能しますが、アプリをpm2などのランチャーで実行している場合やmochaテストを実行している場合、この方法は失敗します。
module.paths
Node は、すべてのモジュール検索パスを に公開しますmodule.paths
。これらをトラバースして、最初に解決したものを選択できます。
async function getAppPath() {
const { dirname } = require('path');
const { constants, promises: { access } } = require('fs');
for (let path of module.paths) {
try {
await access(path, constants.F_OK);
return dirname(path);
} catch (e) {
// Just move on to next path
}
}
}
長所短所
これは機能することもありますが、アプリケーションがインストールされているディレクトリではなく、パッケージがインストールされているディレクトリを返す可能性があるため、パッケージで使用すると信頼できません。
グローバル変数の使用
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というノード モジュールを作成しました。使い方は簡単です:
const appRoot = require('app-root-path');
const myModule = require(`${ appRoot }/lib/my-module.js`);
app-root-pathモジュールは、いくつかの手法を使用して、グローバルにインストールされたモジュールを考慮して、アプリのルート パスを決定します (たとえば、アプリが で実行されている/var/www/
が、モジュールが にインストールされている場合~/.nvm/v0.x.x/lib/node/
)。100% の場合は機能しませんが、ほとんどの一般的なシナリオでは機能します。
長所短所
ほとんどの状況で構成なしで動作します。また、いくつかの便利な追加メソッドも提供します (プロジェクト ページを参照)。最大の短所は、次の場合に機能しないことです。
- pm2 などのランチャーを使用している
- AND、モジュールがアプリの
node_modules
ディレクトリ内にインストールされていない (たとえば、グローバルにインストールした場合)
APP_ROOT_PATH
環境変数を設定するか.setPath()
、モジュールを呼び出すことでこれを回避できますが、その場合は、おそらくglobal
メソッドを使用する方がよいでしょう。
NODE_PATH 環境変数
現在のアプリのルート パスを特定する方法を探している場合は、上記の解決策のいずれかが最適です。一方、アプリ モジュールを確実にロードする問題を解決しようとしている場合は、NODE_PATH
環境変数を調べることを強くお勧めします。
ノードのモジュール システムは、さまざまな場所でモジュールを探します。 これらの場所の 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を参照してください。
1 つの落とし穴: ノード アプリの外部で設定するNODE_PATH
必要があります。モジュールローダーは、アプリの実行前に検索するディレクトリのリストをキャッシュするため、次のようなことはできません。process.env.NODE_PATH = path.resolve(__dirname)
[2016 年 4 月 6 日追加]この問題を解決しようとするもう 1 つの非常に有望なモジュールはwavyです。
__dirname
グローバルではありません。現在のモジュールに対してローカルであるため、各ファイルには独自のローカルの異なる値があります。
実行中のプロセスのルート ディレクトリが必要な場合は、おそらくprocess.cwd()
.
予測可能性と信頼性が必要な場合は、おそらく、特定の環境変数が設定されていることをアプリケーションの要件にする必要があります。あなたのアプリはMY_APP_HOME
(または何でも)探し、そこにあり、アプリケーションがそのディレクトリに存在する場合は、すべて問題ありません。定義されていない場合、またはディレクトリにアプリケーションが含まれていない場合は、ユーザーに変数を作成するように求めるエラーが表示されて終了します。インストールプロセスの一部として設定できます。
のようなものでノードの環境変数を読み取ることができますprocess.env.MY_ENV_VARIABLE
。
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;
このようにして、このファイルに関連するすべてのプロジェクト ディレクトリが作成されます ;)
単純:
require('path').resolve('./')
グローバル ルートを取得する最も簡単な方法 ( 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')
これは、この目的に非常に適しています。
これらすべての「ルートディレクトリ」は、ほとんどの場合、実際のパイルパスへの仮想パスを解決する必要があるため、次を確認する必要がありますpath.resolve
か?
var path= require('path');
var filePath = path.resolve('our/virtual/path.ext');
__filename
が見つかるまでから上に移動してみてpackage.json
、それが現在のファイルが属するメイン ディレクトリであると判断することもできます。
メイン ファイルの先頭に次を追加します。
mainDir = __dirname;
次に、必要なファイルで使用します。
console.log('mainDir ' + mainDir);
mainDir
はグローバルに定義されています。現在のファイルでのみ必要な場合は、__dirname
代わりに使用してください。- メイン ファイルは通常、プロジェクトのルート フォルダーにあり、、、などの名前が付けられ
main.js
ます。index.js
gulpfile.js
node_modules
これにより、通常はプロジェクト ルートを示すディレクトリが含まれるまで、ディレクトリ ツリーが下に移動します。
const fs = require('fs')
const path = require('path')
function getProjectRoot(currentDir = __dirname.split(path.sep)) {
if (!currentDir.length) {
throw Error('Could not find project root.')
}
const nodeModulesPath = currentDir.concat(['node_modules']).join(path.sep)
if (fs.existsSync(nodeModulesPath) && !currentDir.includes('node_modules')) {
return currentDir.join(path.sep)
}
return this.getProjectRoot(currentDir.slice(0, -1))
}
またnode_modules
、ネストされたパッケージのインストールに含まれていることを意味するため、返されたパスに no がないことも確認します。
私はこれを使います。
私のモジュールの名前mymodule
var BASE_DIR = __dirname.replace(/^(.*\/mymodule)(.*)$/, '$1')
これは次のようになります。
path.join(...process.argv[1].split(/\/|\\/).slice(0, -1))
Express アプリ変数にルート ディレクトリ パスを追加するだけで、アプリからこのパスを取得できます。このためapp.set('rootDirectory', __dirname);
に、index.js または app.js ファイルに追加します。req.app.get('rootDirectory')
また、コードでルート ディレクトリ パスを取得するために使用します。
試すpath._makeLong('some_filename_on_root.js');
例:
cons path = require('path');
console.log(path._makeLong('some_filename_on_root.js');
これにより、ノード アプリケーションのルートからのフル パスが返されます (package.json の同じ位置)。
使用するだけです:
path.resolve("./") ... output is your project root directory