1. ホーム
  2. node.js

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

2022-03-22 05:22:05

質問

以外の方法はありますか? process.cwd() 現在のプロジェクトのルートディレクトリのパス名を取得するためです。Nodeはrubyのプロパティのようなものを実装しているのでしょうか? Rails.root ,. 私は、一定で、信頼できるものを探しています。

解決方法は?

アプローチ方法は様々で、それぞれに長所と短所があります。

require.main.filename

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

Nodeから直接ファイルを実行した場合。 require.main には、その module . つまり、あるファイルが実行されたかどうかは、直接 require.main === module

なぜなら module を提供します。 filename プロパティ(通常は __filename をチェックすることで、現在のアプリケーションのエントリポイントを取得することができます。 require.main.filename .

だから、アプリのベースディレクトリが欲しいなら、そうすればいい。

const { dirname } = require('path');
const appDir = dirname(require.main.filename);

長所と短所

ほとんどの場合、この方法はうまくいきますが、もしアプリを pm2 を実行したり モカ のテストでは、このメソッドは失敗します。

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

アプリルートパス

この問題に対処するため、ノードモジュールに アプリルートパス . 使い方は簡単です。

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 を設定します。環境変数の強制をさらに制御したい場合は チェックエンブ .

1つだけガッカリしたことがあります。 NODE_PATH なければならない 決まる 外側 を使用します。のようなことはできません。 process.env.NODE_PATH = path.resolve(__dirname) なぜなら、モジュール・ローダーは、アプリの実行前に検索するディレクトリのリストをキャッシュするからです。

[2016/4/6追記]です。 この問題を解決しようとする、もうひとつの有望なモジュールは 波状 .