503 Stimmen

Ermitteln des Projektstamms aus einer laufenden node.js-Anwendung

Gibt es einen anderen Weg, außer process.cwd() , um den Pfadnamen des Root-Verzeichnisses des aktuellen Projekts zu erhalten. Implementiert Node so etwas wie die Eigenschaft von Ruby, Rails.root ,. Ich bin auf der Suche nach etwas, das konstant und zuverlässig ist.

881voto

inxilpro Punkte 18839

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

require.main.filename

De http://nodejs.org/api/modules.html :

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

Denn module bietet eine filename Eigenschaft (normalerweise gleichbedeutend mit __filename ), kann der Einstiegspunkt der aktuellen Anwendung ermittelt werden, indem die require.main.filename .

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

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

Pro und Kontra

Dies wird in den meisten Fällen gut funktionieren, aber wenn Sie Ihre Anwendung mit einem Launcher wie pm2 oder Laufen Mokka Tests, wird diese Methode fehlschlagen. Dies wird auch nicht funktionieren, wenn Sie Node.js ES-Module verwenden, bei denen require.main ist nicht verfügbar.

module.paths

Der Knoten veröffentlicht alle Modulsuchpfade auf module.paths . Wir können diese durchgehen und die erste auswählen, die sich auflöst.

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
    }
  }
}

Pro und Kontra

Dies funktioniert manchmal, ist aber nicht zuverlässig, wenn es in einem Paket verwendet wird, da es möglicherweise das Verzeichnis zurückgibt, in dem das Paket installiert ist, und nicht das Verzeichnis, in dem die Anwendung installiert ist.

Verwendung einer globalen Variablen

Node hat ein globales Namespace-Objekt namens global - Alles, was Sie diesem Objekt zuordnen, wird überall in Ihrer Anwendung verfügbar sein. Also, in Ihrer index.js (o app.js oder was auch immer Ihre Hauptanwendung Datei benannt ist), 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 und Kontra

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

process.cwd()

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

$ 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-Pfad

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

const appRoot = require('app-root-path');
const myModule = require(`${ appRoot }/lib/my-module.js`);

En app-Root-Pfad Modul verwendet verschiedene Techniken, um den Root-Pfad der Anwendung zu bestimmen, wobei global installierte Module berücksichtigt werden (wenn Ihre Anwendung beispielsweise in /var/www/ aber das Modul ist installiert in ~/.nvm/v0.x.x/lib/node/ ). Das wird nicht immer zu 100 % funktionieren, aber in den meisten Fällen schon.

Pro und 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 verwenden einen Launcher, wie pm2
  • UND ist das Modul nicht innerhalb der App installiert. node_modules (zum Beispiel, wenn Sie es global installiert haben)

Sie können dies umgehen, indem Sie entweder eine APP_ROOT_PATH Umgebungsvariable, oder durch den Aufruf von .setPath() auf dem Modul, aber in diesem Fall sind Sie wahrscheinlich besser dran, wenn Sie die global Methode.

NODE_PATH Umgebungsvariable

Wenn Sie nach einem Weg suchen, um ermitteln. Wenn Sie den Root-Pfad der aktuellen Anwendung nicht kennen, ist eine der oben genannten Lösungen für Sie wahrscheinlich am besten geeignet. Wenn Sie hingegen versuchen, das Problem des zuverlässigen Ladens von App-Modulen zu lösen, empfehle ich Ihnen dringend, sich mit dem NODE_PATH Umweltvariable.

Knotens Module System sucht nach Modulen an verschiedenen Orten. Einer dieser Orte ist der Ort process.env.NODE_PATH Punkte . Wenn Sie diese Umgebungsvariable setzen, dann können Sie require Module mit dem Standard-Modul-Loader ohne weitere Änderungen.

Zum Beispiel, wenn Sie NODE_PATH a /var/www/lib würde das Folgende sehr gut 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 und Sie sind glücklich. Ich kombiniere das mit meinem enforce-node-path Modul, das ein versehentliches Laden der Anwendung ohne NODE_PATH gesetzt. Für noch mehr Kontrolle über die Erzwingung von Umgebungsvariablen, siehe checkenv .

Ein Problem: NODE_PATH doit eingestellt werden außerhalb der Knoten-App. Sie können nicht etwas tun wie process.env.NODE_PATH = path.resolve(__dirname) weil der Modullader die Liste der Verzeichnisse, die er durchsucht, bevor Ihre Anwendung ausgeführt wird, im Cache speichert.

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

95voto

izb Punkte 47624

__dirname ist kein globaler, sondern ein lokaler Wert für das aktuelle Modul, so dass jede Datei ihren eigenen lokalen, unterschiedlichen Wert hat.

Wenn Sie das Root-Verzeichnis des laufenden Prozesses wollen, sollten Sie wahrscheinlich die Option process.cwd() .

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

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

60voto

Vansuita Jr. Punkte 1763

Einfach:

require('path').resolve('./')

58voto

Fareed Alnamrouti Punkte 28431

1- Erstellen Sie eine Datei im Projekt Root und nennen Sie sie einstellungen.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 ;)

45voto

Alexander Mills Punkte 76733

Der einfachste Weg, um die globale Wurzel ( vorausgesetzt, Sie verwenden NPM, um Ihre node.js-Anwendung auszuführen: 'npm start' usw. )

var appRoot = process.env.PWD;

Wenn Sie die obigen Angaben gegenprüfen möchten

Nehmen wir an, Sie wollen eine Gegenprobe machen process.env.PWD mit den Einstellungen Ihrer node.js-Anwendung. Wenn Sie einige Laufzeittests zur Überprüfung der Gültigkeit von process.env.PWD können Sie es mit diesem Code vergleichen (den ich geschrieben habe und der gut zu funktionieren scheint). Sie können den Namen des letzten Ordners in appRoot zum Beispiel mit dem npm_package_name in Ihrer package.json-Datei abgleichen:

    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.');
    }

können Sie auch dieses NPM-Modul verwenden: require('app-root-path') die für diesen Zweck sehr gut geeignet ist

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X