Ermitteln des Projektstamms aus einer laufenden node.js-Anwendung

Gibt es einen besseren Weg als process.cwd(), um das Stammverzeichnis eines laufenden Node.js-Prozesses zu ermitteln? Etwas wie das Äquivalent von Rails.root, aber für Node.js. Ich bin auf der Suche nach etwas, das so vorhersehbar und zuverlässig wie möglich ist.

Lösung

Es gibt verschiedene Möglichkeiten, dies zu tun, jede mit ihren eigenen Vor- und Nachteilen:

require.main.filename

Von :

Wenn eine Datei direkt von Node ausgeführt wird, wird require.main auf ihr modul gesetzt. Das bedeutet, dass Sie feststellen können, ob eine Datei direkt ausgeführt wurde, indem Sie require.main === module testen

Da module eine filename-Eigenschaft bietet (normalerweise äquivalent zu __filename), kann der Einstiegspunkt der aktuellen Anwendung durch Überprüfung von require.main.filename ermittelt werden.

Wenn Sie also das Basisverzeichnis für Ihre Anwendung wollen, können Sie das tun:

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

Pro & Kontra

Dies wird die meiste Zeit gut funktionieren, aber wenn Sie Ihre App mit einem Launcher wie pm2 ausführen oder mocha Tests durchführen, wird diese Methode fehlschlagen.

global.X

Node hat ein globales Namespace-Objekt namens global - alles, was Sie an dieses Objekt anhängen, wird überall in Ihrer App verfügbar sein. Also, in Ihrer index.js (oder app.js oder wie auch immer Ihre Haupt-App-Datei heißt), können Sie einfach eine globale Variable definieren:

// index.js
var path = require('path');
global.appRoot = path.resolve(__dirname);

// lib/moduleA/component1.js
require(appRoot + '/lib/moduleB/component2.js');

Pro & Kontra

Funktioniert konsistent, aber man ist auf eine globale Variable angewiesen, was bedeutet, dass man Komponenten etc. nicht einfach wiederverwenden kann.

process.cwd()

Dies gibt das aktuelle Arbeitsverzeichnis zurück. Überhaupt nicht zuverlässig, da es völlig davon abhängt, von welchem Verzeichnis aus der Prozess gestartet wurde**:

$ 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

Um dieses Problem zu lösen, habe ich ein Knotenmodul namens app-root-path erstellt. Die Verwendung ist einfach:

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

Das app-root-path Modul verwendet verschiedene Techniken, um den Wurzelpfad der Anwendung zu bestimmen, wobei global installierte Module berücksichtigt werden (z.B. wenn Ihre Anwendung in /var/www/ läuft, aber das Modul in ~/.nvm/v0.x.x/lib/node/ installiert ist). Es wird nicht in 100% der Fälle funktionieren, aber in den meisten Fällen wird es funktionieren.

Pro & Kontra

Funktioniert unter den meisten Umständen ohne Konfiguration. Bietet auch einige nette zusätzliche Komfortmethoden (siehe Projektseite). Der größte Nachteil ist, dass es nicht funktionieren wird, wenn:

  • Sie einen Launcher verwenden, wie pm2
  • UND, das Modul nicht im Verzeichnis node_modules Ihrer Anwendung installiert ist (zum Beispiel, wenn Sie es global installiert haben)

Sie können dies umgehen, indem Sie entweder eine APP_ROOT_PATH Umgebungsvariable setzen, oder indem Sie .setPath() für das Modul aufrufen, aber in diesem Fall sind Sie wahrscheinlich besser dran, wenn Sie die global Methode verwenden.

NODE_PATH Umgebungsvariable

Wenn Sie nach einer Möglichkeit suchen, den Wurzelpfad der aktuellen Anwendung zu bestimmen, ist eine der obigen Lösungen wahrscheinlich am besten für Sie geeignet. Wenn Sie andererseits versuchen, das Problem des zuverlässigen Ladens von Anwendungsmodulen zu lösen, empfehle ich Ihnen, sich die Umgebungsvariable NODE_PATH anzusehen.

Node's Modules system sucht an verschiedenen Stellen nach Modulen. Einer dieser Orte ist dort, wo process.env.NODE_PATH hinzeigt. Wenn Sie diese Umgebungsvariable setzen, dann können Sie Module mit dem Standard-Modul-Loader ohne weitere Änderungen fordern.

Wenn Sie z.B. NODE_PATH auf /var/www/lib setzen, würde das Folgende problemlos funktionieren:

require('module2/component.js');
// ^ looks for /var/www/lib/module2/component.js

Eine gute Möglichkeit, dies zu tun, ist die Verwendung von npm:

"scripts": {
    "start": "NODE_PATH=. node app.js"
}

Jetzt können Sie Ihre Anwendung mit npm start starten und Sie sind glücklich. Ich kombiniere dies mit meinem enforce-node-path Modul, das verhindert, dass die App versehentlich ohne gesetzten NODE_PATH geladen wird. Für noch mehr Kontrolle über das Erzwingen von Umgebungsvariablen, siehe checkenv.

Ein kleiner Haken: NODE_PATH muss außerhalb der Node-App gesetzt werden. Sie können nicht etwas wie process.env.NODE_PATH = path.resolve(__dirname) machen, weil der Modul-Loader die Liste der Verzeichnisse, die er durchsucht, zwischenspeichert, bevor Ihre Anwendung läuft.

[hinzugefügt 4/6/16] Ein weiteres vielversprechendes Modul, das versucht, dieses Problem zu lösen, ist wavy.

Kommentare (22)

__dirname ist nicht global, sondern lokal für das aktuelle Modul, so dass jede Datei ihren eigenen lokalen, unterschiedlichen Wert hat.

Wenn Sie das Stammverzeichnis des laufenden Prozesses wollen, sollten Sie wahrscheinlich process.cwd() verwenden.

Wenn Sie Vorhersagbarkeit und Zuverlässigkeit wollen, dann müssen Sie wahrscheinlich eine bestimmte Umgebungsvariable als Voraussetzung für Ihre Anwendung setzen. Ihre Anwendung sucht nach MY_APP_HOME (oder was auch immer) und wenn es dort ist, und die Anwendung in diesem Verzeichnis existiert, dann ist alles gut. Wenn sie undefiniert ist oder das Verzeichnis Ihre Anwendung nicht enthält, sollte sie sich mit einer Fehlermeldung beenden und den Benutzer auffordern, die Variable zu erstellen. Sie könnte als Teil eines Installationsprozesses gesetzt werden.

Sie können Umgebungsvariablen in Node mit etwas wie process.env.MY_ENV_VARIABLE auslesen.

Kommentare (2)

1- Erstellen Sie eine Datei im Stammverzeichnis des Projekts und nennen Sie sie settings.js.

2- fügen Sie innerhalb dieser Datei folgenden Code ein

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

3- Erstellen Sie innerhalb von node_modules ein neues Modul mit dem Namen "settings" und schreiben Sie innerhalb des Moduls index.js diesen Code:

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

4- und jedes Mal, wenn Sie Ihr Projektverzeichnis benötigen, verwenden Sie einfach

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

auf diese Weise haben Sie alle Projektverzeichnisse relativ zu dieser Datei ;)

Kommentare (9)