Déterminer la racine du projet à partir d'un nœud en cours d'exécution.application js

Est-il un meilleur moyen que le process.cwd() pour déterminer le répertoire racine d'un nœud en cours d'exécution.processus js? Quelque chose comme l'équivalent de Rails.root, mais pour le Nœud.js. Je cherche quelque chose qui est aussi prévisible et fiable que possible.

225
demandé sur MrEvil 2012-04-22 10:39:20

19 réponses

Il y a plusieurs façons d'aborder cela, chacune avec ses propres avantages et inconvénients:

Exiger.principal.nom du fichier

À Partir de http://nodejs.org/api/modules.html:

Lorsqu'un fichier est exécuté directement à partir du Nœud, require.main est défini à sa module. Cela signifie que vous pouvez déterminer si un fichier a été exécuté directement en testant require.main === module

Étant donné que module fournit une propriété filename (normalement équivalente à __filename), le point d'entrée de l'application courante peut être obtenu en cochant require.main.filename.

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

var path = require('path');
var appDir = path.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 Mocha tests, cette méthode échouera.

Mondial.X

Node a un objet d'espace de noms global appelé global - Tout ce que vous attachez à cet objet sera disponible partout dans votre application. Si, dans votre index.js (ou app.js ou quel que soit le nom de votre fichier d'application principal), 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 compter sur une variable globale, ce qui signifie que vous ne pouvez pas facilement réutiliser les composants/etc.

Processus.mdc()

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é à partir 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-racine-chemin. L'utilisation est simple:

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

Le app-racine-chemin le module utilise plusieurs techniques différentes 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 /var/www/ mais que le module est installé dans ~/.nvm/v0.x.x/lib/node/). Cela ne fonctionnera pas 100% du temps, mais c'est aller travailler dans la plupart des scénarios courants.

Avantages Et Inconvénients

Fonctionne sans configuration dans la plupart des cas. Fournit également quelques belles méthodes de commodité supplémentaires (voir la page du projet). Le plus gros inconvénient est que cela ne fonctionnera pas si:

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

Vous pouvez contourner cela par l'un ou l'autre paramètre une variable d'environnement APP_ROOT_PATH, ou en appelant .setPath() sur le module, mais dans ce cas, il vaut probablement mieux utiliser la méthode global.

Variable D'environnement NODE_PATH

Si vous cherchez un moyen de déterminer le chemin racine de l'application en cours, l'une des solutions ci-dessus est susceptible de fonctionner le mieux pour vous. Si, d'un autre côté, vous essayez de résoudre le problème du chargement des modules d'application de manière fiable, je vous recommande fortement de regarder dans l'environnement NODE_PATH variable.

Le système de Modules du nœud recherche les modules dans divers emplacements. l'Un de ces endroits où process.env.NODE_PATH points. Si vous définissez cette variable d'environnement, vous pouvez require modules avec le chargeur de module standard sans autres modifications.

Par exemple, si vous définissez NODE_PATH sur /var/www/lib, ce qui suit fonctionnera très bien:

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

Une excellente façon de le faire est d'utiliser npm:

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

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

Un gotcha: NODE_PATH doit être ensemble dehors de du nœud de l'application. Vous ne pouvez pas faire quelque chose comme process.env.NODE_PATH = path.resolve(__dirname) car le chargeur de module met en cache la liste des répertoires qu'il recherchera avant votre application exécuter.

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

449
répondu inxilpro 2016-04-07 03:46:48

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

Si vous voulez le répertoire racine du processus en cours, vous voulez 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 si elle est là, et que l'application existe dans ce répertoire, tout est Bien. S'il n'est pas défini ou si le répertoire ne contient pas votre application, il devrait sortir avec une erreur invitant l'utilisateur à créer la variable. Il pourrait être défini dans le cadre d'un processus d'installation.

Vous pouvez lire les variables d'environnement dans le nœud avec quelque chose comme process.env.MY_ENV_VARIABLE.

43
répondu izb 2016-03-30 19:23:09

1 - créer un fichier dans la racine du projet de l'appeler paramètres.js

2-à l'intérieur de ce fichier ajouter ce code

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

3 - inside node_modules créer un nouveau nom de module "paramètres" et à l'intérieur de l'index du module.js écrire ce code:

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

4-et chaque fois que vous voulez que votre répertoire de projet utilise simplement

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

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

40
répondu Fareed Alnamrouti 2013-11-22 20:36:23

Le moyen le plus simple d'obtenir la racine globale (en supposant que vous utilisez NPM pour exécuter votre nœud.js app 'npm démarrer", etc)

var appRoot = process.env.PWD;

Si vous voulez vérifier le{[8 ci-dessus]}

Dites que vous voulez recouper process.env.PWD avec les paramètres de votre nœud.application js. si vous voulez que certains tests d'exécution vérifient la validité de process.env.PWD, Vous pouvez le recouper avec ce code (que j'ai écrit et qui semble bien fonctionner). Vous pouvez recouper le nom du dernier dossier dans appRoot avec le npm_package_name dans votre paquet.fichier 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

13
répondu Alexander Mills 2015-11-08 04:39:33

J'ai trouvé que cela fonctionne de manière cohérente pour moi, même lorsque l'application est appelée à partir d'un sous-dossier, comme cela peut être le cas avec certains frameworks de test, comme Mocha:

process.mainModule.paths[0].split('node_modules')[0].slice(0, -1);

Pourquoi cela fonctionne:

Au noeud d'exécution crée un registre des chemins complets de tous les fichiers chargés. Les modules sont chargés en premier, et donc en haut de ce registre. En sélectionnant le premier élément du registre et en retournant le chemin avant le répertoire 'node_modules', nous sommes en mesure de déterminer la racine du application.

C'est juste une ligne de code, mais pour des raisons de simplicité (mon bien), je l'ai encadré en noir dans un module NPM:

Https://www.npmjs.com/package/node-root.pddivine

Profitez!

10
répondu Patrick 2017-05-14 06:08:39

Tous ces "root dirs" ont surtout besoin de résoudre un chemin virtuel vers un chemin de pile réel, alors peut-être que vous devriez regarder path.resolve?

var path= require('path');
var filePath = path.resolve('our/virtual/path.ext");
6
répondu Konstantin Isaev 2015-01-09 21:18:25

Peut-être que vous pouvez essayer de traverser vers le haut à partir de __filename jusqu'à ce que vous trouviez un package.json, et décidez que c'est le répertoire principal auquel appartient votre fichier actuel.

6
répondu kvz 2015-06-19 16:04:45

Une technique que j'ai trouvée utile lors de l'utilisation d'express consiste à ajouter ce qui suit à l'application.js avant que l'une de vos autres routes ne soit définie

// set rootPath
app.use(function(req, res, next) {
  req.rootPath = __dirname;
  next();
});

app.use('/myroute', myRoute);

Pas besoin d'utiliser des globals et vous avez le chemin du répertoire racine comme propriété de l'objet request.

Cela fonctionne si votre application.js est à la racine de votre projet qui, par défaut, il est.

2
répondu Ben Davies 2015-08-10 10:51:28

En fait, je trouve la solution peut-être triviale aussi la plus robuste: vous placez simplement le fichier suivant dans le répertoire racine de votre projet: root-path.js qui a le code suivant:

import * as path from 'path' const projectRootPath = path.resolve(__dirname) export const rootPath = projectRootPath

2
répondu Avi Tshuva 2017-02-05 11:17:46

J'utilise ceci.

Pour mon module nommé mymodule

var BASE_DIR = __dirname.replace(/^(.*\/mymodule)(.*)$/, '$1')

1
répondu vbranden 2016-12-02 15:08:23

Créer une fonction dans l'application.js

/*Function to get the app root folder*/

var appRootFolder = function(dir,level){
    var arr = dir.split('\\');
    arr.splice(arr.length - level,level);
    var rootFolder = arr.join('\\');
    return rootFolder;
}

// view engine setup
app.set('views', path.join(appRootFolder(__dirname,1),'views'));
0
répondu Karthik M 2015-03-01 04:59:49

En haut du fichier principal Ajouter:

mainDir = __dirname;

Ensuite, utilisez-le dans n'importe quel fichier dont vous avez besoin:

console.log('mainDir ' + mainDir);
  • {[2] } est défini globalement, Si vous en avez besoin uniquement dans le fichier actuel-utilisez __dirname à la place.
  • le fichier principal est généralement dans le dossier racine du projet et est nommé comme main.js, index.js, gulpfile.js.
0
répondu Dariusz Sikorski 2016-05-28 06:58:54

Rendez-le sexy .

const users = require('../../../database/users'); //  what you have
// OR
const users = require('$db/users'); //  no matter how deep you are
const products = require('/database/products'); //  alias or pathing from root directory


Trois étapes simples pour résoudre le problème du chemin laid.

  1. Installer le paquet: npm install sexy-require --save
  2. Incluez require('sexy-require') Une fois en haut de votre fichier d'application principal.

    require('sexy-require');
    const routers = require('/routers');
    const api = require('$api');
    ...
    
  3. Étape facultative. La configuration du chemin peut être définie dans le fichier .paths du répertoire racine de votre projet.

    $db = /server/database
    $api-v1 = /server/api/legacy
    $api-v2 = /server/api/v2
    
0
répondu sultan 2018-01-12 17:50:19
process.mainModule.paths
  .filter(p => !p.includes('node_modules'))
  .shift()

Récupère tous les chemins dans les modules principaux et filtre ceux avec " node_modules", ensuite, obtenez le premier de la liste de chemin restante. Un comportement inattendu ne lancera pas d'erreur, juste un undefined.

Fonctionne bien pour moi, même en appelant ie $ mocha.

0
répondu Andre Figueiredo 2018-03-18 00:59:04

Vous pouvez simplement ajouter le chemin du répertoire racine dans la variable express app et obtenir ce chemin à partir de l'application. Pour cela, ajoutez app.set('rootDirectory', __dirname); dans votre index.js ou de l'application.fichier js. Et utilisez req.app.get('rootDirectory') pour obtenir le chemin du répertoire racine dans votre code.

0
répondu Pulkit Aggarwal 2018-06-24 10:15:19

Ancienne question, je sais, mais aucune mention de question à utiliser progress.argv. Le tableau argv inclut un chemin d'accès complet et un nom de fichier (avec ou sans .extension js) qui a été utilisé comme paramètre à exécuter par le nœud. Parce que cela peut également contenir des drapeaux, vous devez filtrer cela.

Ce n'est pas un exemple que vous pouvez utiliser directement (en raison de l'utilisation de mon propre framework) mais je pense que cela vous donne une idée de la façon de le faire. J'utilise également une méthode de cache pour éviter que l'appel de cette fonction ne mette trop l'accent sur le système, surtout quand aucune extension n'est spécifiée (et qu'un fichier existe est requis), par exemple:

node myfile

Ou

node myfile.js

C'est la raison pour laquelle je le cache, voir aussi le code ci-dessous.


function getRootFilePath()
{
        if( !isDefined( oData.SU_ROOT_FILE_PATH ) )
        {
            var sExt = false;

            each( process.argv, function( i, v )
            {
                 // Skip invalid and provided command line options
                if( !!v && isValidString( v ) && v[0] !== '-' )
                {
                    sExt = getFileExt( v );

                    if( ( sExt === 'js' ) || ( sExt === '' && fileExists( v+'.js' )) )
                    {

                        var a = uniformPath( v ).split("/"); 

                         // Chop off last string, filename
                        a[a.length-1]='';

                         // Cache it so we don't have to do it again.
                        oData.SU_ROOT_FILE_PATH=a.join("/"); 

                         // Found, skip loop
                        return true;
                    }
                }
            }, true ); // <-- true is: each in reverse order
        }

        return oData.SU_ROOT_FILE_PATH || '';
    }
}; 
0
répondu Codebeat 2018-09-27 03:07:08

Ajoutez ceci quelque part vers le début de votre fichier d'application principal (par exemple, app.js):

global.__basedir = __dirname;

Cela définit une variable globale qui sera toujours équivalente au répertoire de base de votre application. S'utilise comme n'importe quelle autre variable:

const yourModule = require(__basedir + '/path/to/module.js');

Simple...

0
répondu Pankaj Shinde 2018-10-05 08:11:28

Essayez path._makeLong('some_filename_on_root.js');

Exemple:

cons path = require('path');
console.log(path._makeLong('some_filename_on_root.js');

Qui retournera le chemin complet de la racine de votre application node (même position du paquet.json)

-1
répondu The-x Laws 2016-06-28 18:38:36

Pour obtenir le chemin du fichier actuel:

définir dans ce fichier:


    var get_stack = function() {
        var orig = Error.prepareStackTrace;
        Error.prepareStackTrace = function(_, stack) {
            return stack;
        };
        var err = new Error;
        Error.captureStackTrace(err, arguments.callee);
        var stack = err.stack;
        Error.prepareStackTrace = orig;
        return stack;
    };

Utilisation dans ce fichier:


    console.log(get_stack()[0].getFileName());

API:
StackTrace

-2
répondu user1012316 2015-10-08 03:58:15