492 votes

Déterminer la racine du projet à partir d'une application node.js en cours d'exécution

Y a-t-il un autre moyen, autre que process.cwd() pour obtenir le nom du chemin du répertoire racine du projet en cours. Est-ce que Node implémente quelque chose comme la propriété de Ruby, Rails.root ,. Je cherche quelque chose qui soit constant et fiable.

869voto

inxilpro Points 3475

Il existe de nombreuses façons d'aborder cette question, chacune ayant ses avantages et ses inconvénients :

require.main.filename

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

Lorsqu'un fichier est exécuté directement depuis Node, require.main est fixé à son module . Cela signifie que vous pouvez déterminer si un fichier a été exécuté directement en testant require.main === module

Porque module fournit un filename (normalement équivalent à __filename ), le point d'entrée de l'application courante peut être obtenu en vérifiant require.main.filename .

Donc si vous voulez le répertoire de base pour votre application, vous pouvez le faire :

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

Avantages et inconvénients

Cela fonctionnera très bien la plupart du temps, mais si vous exécutez votre application avec un lanceur comme pm2 ou en cours d'exécution moka cette méthode échouera.

module.paths

Le nœud publie tous les chemins de recherche de modules sur le site web de l'entreprise. module.paths . Nous pouvons les parcourir et choisir le premier qui se résout.

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

Avantages et inconvénients

Cette méthode fonctionne parfois, mais n'est pas fiable lorsqu'elle est utilisée dans un paquet, car elle peut renvoyer le répertoire dans lequel le paquet est installé plutôt que le répertoire dans lequel l'application est installée.

Utilisation d'une variable globale

Node possède un objet d'espace de nom global appelé global - Tout ce que vous attachez à cet objet sera disponible partout dans votre application. Ainsi, dans votre index.js (ou app.js ou quelle que soit votre application principale ), vous pouvez simplement définir une variable globale :

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

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

Avantages et inconvénients

Fonctionne de manière cohérente, mais vous devez vous appuyer sur une variable globale, ce qui signifie que vous ne pouvez pas réutiliser facilement les composants/etc.

process.cwd()

Ceci renvoie le répertoire de travail actuel. Pas fiable du tout, car il dépend entièrement du répertoire dans lequel le processus a été lancé. de :

$ 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

Pour résoudre ce problème, j'ai créé un module de nœud appelé app-Root-path . L'utilisation est simple :

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

El app-Root-path utilise plusieurs techniques pour déterminer le chemin racine de l'application, en tenant compte des modules installés globalement (par exemple, si votre application s'exécute dans le répertoire /var/www/ mais le module est installé dans ~/.nvm/v0.x.x/lib/node/ ). Cela ne fonctionnera pas dans 100 % des cas, mais dans la plupart des cas.

Avantages et inconvénients

Fonctionne sans configuration dans la plupart des cas. Il fournit également quelques méthodes supplémentaires très pratiques (voir la page du projet). Le plus gros inconvénient est qu'il ne fonctionnera pas si :

  • Vous utilisez un lanceur, comme pm2.
  • ET le module n'est pas installé dans le répertoire de votre application. node_modules (par exemple, si vous l'avez installé globalement)

Vous pouvez contourner ce problème en définissant un APP_ROOT_PATH ou en appelant la variable environnementale .setPath() sur le module, mais dans ce cas, il est probablement préférable d'utiliser l'option global méthode.

Variable environnementale NODE_PATH

Si vous cherchez un moyen de déterminer le chemin racine de l'application actuelle, l'une des solutions ci-dessus est susceptible de fonctionner au mieux pour vous. Si, en revanche, vous essayez de résoudre le problème du chargement fiable des modules d'application, je vous recommande vivement de vous pencher sur l'option NODE_PATH variable environnementale.

Node's Système de modules recherche des modules dans différents endroits. L'un de ces lieux est l'endroit où process.env.NODE_PATH points . Si vous définissez cette variable d'environnement, vous pouvez alors require avec le chargeur de modules standard sans autre modification.

Par exemple, si vous définissez NODE_PATH a /var/www/lib le texte suivant fonctionnerait très bien :

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

Un bon moyen de le faire est d'utiliser npm :

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

Vous pouvez maintenant démarrer votre application avec npm start et vous êtes en or. Je combine ça avec mon enforce-node-path qui empêche le chargement accidentel de l'application sans le module NODE_PATH set. Pour encore plus de contrôle sur l'application des variables environnementales, voir checkenv .

Un "gotcha" : NODE_PATH doit être fixé à l'extérieur de de l'application du nœud. Vous ne pouvez pas faire quelque chose comme process.env.NODE_PATH = path.resolve(__dirname) car le chargeur de modules met en cache la liste des répertoires qu'il va rechercher avant l'exécution de votre application.

[ajouté le 4/6/16] Un autre module très prometteur qui tente de résoudre ce problème est le suivant ondulé .

92voto

izb Points 12736

__dirname n'est pas global ; il est local au module actuel, donc chaque fichier a sa propre valeur locale, différente.

Si vous voulez le répertoire racine du processus en cours, vous voudrez probablement utiliser process.cwd() .

Si vous voulez de la prévisibilité et de la fiabilité, vous devez probablement exiger de votre application qu'une certaine variable d'environnement soit définie. Votre application recherche MY_APP_HOME (ou autre) et s'il est là, et que l'application existe dans ce répertoire, alors tout va bien. Si elle n'est pas définie ou si le répertoire ne contient pas votre application, elle doit sortir avec une erreur invitant l'utilisateur à créer la variable. Elle pourrait être définie dans le cadre d'un processus d'installation.

Vous pouvez lire les variables d'environnement dans node avec quelque chose comme process.env.MY_ENV_VARIABLE .

56voto

fareed namrouti Points 3830

1- créer un fichier dans le projet Root l'appeler settings.js

2- dans ce fichier, ajoutez ce code

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

3- dans node_modules créez un nouveau module nommé "settings" et dans le module index.js écrivez ce code :

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

4- et à chaque fois que vous voulez le répertoire de votre projet, utilisez simplement

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

de cette façon, vous aurez tous les répertoires du projet relatifs à ce fichier ;)

55voto

Vansuita Jr. Points 900

Simple :

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

45voto

Alex Mills Points 635

Le moyen le plus simple d'obtenir la racine globale ( en supposant que vous utilisez NPM pour exécuter votre application node.js "npm start", etc. )

var appRoot = process.env.PWD;

Si vous voulez vérifier ce qui précède

Disons que vous voulez faire une vérification croisée process.env.PWD avec les paramètres de votre application node.js. Si vous souhaitez que des tests d'exécution vérifient la validité de l'application node.js, vous pouvez utiliser les paramètres de l'application. process.env.PWD vous pouvez le vérifier avec ce code (que j'ai écrit et qui semble bien fonctionner). Vous pouvez croiser le nom du dernier dossier dans appRoot avec le npm_package_name dans votre fichier package.json, par exemple :

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

vous pouvez également utiliser ce module NPM : require('app-root-path') qui fonctionne très bien à cet effet

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X