¿Existe una forma mejor que process.cwd()
para determinar el directorio raíz de un proceso node.js en ejecución? Algo así como el equivalente a Rails.root
, pero para Node.js. Busco algo que sea lo más predecible y fiable posible.
Hay varias maneras de enfocar esto, cada una con sus propios pros y contras:
Desde http://nodejs.org/api/modules.html:
Cuando un archivo se ejecuta directamente desde Node, require.main
se establece en su módulo
. Esto significa que puedes determinar si un archivo ha sido ejecutado directamente probando require.main === module
.
Dado que
module
proporciona una propiedadfilename
(normalmente equivalente a__filename
), el punto de entrada de la aplicación actual puede obtenerse comprobandorequire.main.filename
.
Así que si quieres el directorio base de tu aplicación, puedes hacerlo:
var path = require('path');
var appDir = path.dirname(require.main.filename);
Esto funcionará muy bien la mayor parte del tiempo, pero si estás ejecutando tu aplicación con un lanzador como pm2 o ejecutando pruebas mocha, este método fallará.
Node tiene un objeto de espacio de nombres global llamado global
- cualquier cosa que adjuntes a este objeto estará disponible en toda tu aplicación. Así que, en tu index.js
(o app.js
o como sea que se llame el archivo principal de tu aplicación), puedes definir una variable global:
// index.js
var path = require('path');
global.appRoot = path.resolve(__dirname);
// lib/moduleA/component1.js
require(appRoot + '/lib/moduleB/component2.js');
Funciona de forma consistente pero tienes que depender de una variable global, lo que significa que no puedes reutilizar fácilmente los componentes/etc.
Esto devuelve el directorio de trabajo actual. No es fiable en absoluto, ya que depende totalmente del directorio desde el que se inició el proceso:
$ 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
Para solucionar este problema, he creado un módulo de nodo llamado app-root-path. Su uso es sencillo:
var appRoot = require('app-root-path');
var myModule = require(appRoot + '/lib/my-module.js');
El módulo app-root-path utiliza varias técnicas diferentes para determinar la ruta raíz de la aplicación, teniendo en cuenta los módulos instalados globalmente (por ejemplo, si tu aplicación se ejecuta en /var/www/
pero el módulo está instalado en ~/.nvm/v0.x.x/lib/node/
). No funcionará el 100% de las veces, pero sí en la mayoría de los casos.
Funciona sin configuración en la mayoría de las circunstancias. También proporciona algunos buenos métodos adicionales de conveniencia (véase la página del proyecto). La mayor desventaja es que no funcionará si:
node_modules
de tu aplicación (por ejemplo, si lo instalaste globalmente)Puedes evitarlo estableciendo una variable de entorno APP_ROOT_PATH
, o llamando a .setPath()
en el módulo, pero en ese caso, probablemente sea mejor usar el método global
.
Si está buscando una forma de determinar la ruta raíz de la aplicación actual, es probable que una de las soluciones anteriores le funcione mejor. Si, por otro lado, estás tratando de resolver el problema de la carga de los módulos de la aplicación de forma fiable, te recomiendo encarecidamente que mires la variable de entorno NODE_PATH
.
El [sistema de módulos] de Node (https://nodejs.org/api/modules.html) busca módulos en una variedad de ubicaciones. Uno de estos lugares es donde apunta process.env.NODE_PATH
. Si establece esta variable de entorno, entonces puede requerir
módulos con el cargador de módulos estándar sin ningún otro cambio.
Por ejemplo, si estableces NODE_PATH
a /var/www/lib
, lo siguiente funcionará bien:
require('module2/component.js');
// ^ looks for /var/www/lib/module2/component.js
Una buena manera de hacer esto es usando npm
:
"scripts": {
"start": "NODE_PATH=. node app.js"
}
Ahora puedes iniciar tu aplicación con npm start
y ya estás listo. Combino esto con mi módulo enforce-node-path, que previene la carga accidental de la aplicación sin el NODE_PATH
establecido. Para un mayor control sobre la aplicación de las variables de entorno, vea checkenv.
Un inconveniente: NODE_PATH
debe establecerse fuera de la aplicación node. No puedes hacer algo como process.env.NODE_PATH = path.resolve(__dirname)
porque el cargador de módulos almacena en caché la lista de directorios que buscará antes de que tu aplicación se ejecute.
[añadido el 4/6/16] Otro módulo realmente prometedor que intenta resolver este problema es wavy.
__dirname
no es global; es local para el módulo actual, por lo que cada archivo tiene su propio valor local y diferente.
Si quiere el directorio raíz del proceso en ejecución, probablemente quiera usar process.cwd()
.
Si quieres predictibilidad y fiabilidad, entonces probablemente necesites hacer un requisito de tu aplicación que una determinada variable de entorno esté establecida. Tu aplicación busca MY_APP_HOME
(o lo que sea) y si está ahí, y la aplicación existe en ese directorio entonces todo está bien. Si no está definida o el directorio no contiene su aplicación, entonces debería salir con un error pidiendo al usuario que cree la variable. Se puede establecer como parte de un proceso de instalación.
Puedes leer las variables de entorno en node con algo como process.env.MY_ENV_VARIABLE
.
1- crea un archivo en la raíz del proyecto llámalo settings.js
2- dentro de este archivo añade este código
module.exports = {
POST_MAX_SIZE : 40 , //MB
UPLOAD_MAX_FILE_SIZE: 40, //MB
PROJECT_DIR : __dirname
};
3- dentro de node_modules crea un nuevo módulo llámalo "settings" y dentro del módulo index.js escribe este código:
module.exports = require("../../settings");
4- y cada vez que quieras el directorio de tu proyecto solo usa
var settings = require("settings");
settings.PROJECT_DIR;
de esta forma tendrás todos los directorios del proyecto relativos a este archivo ;)