Trabajando con Variables de entorno en Node

February 10, 2022
Redactado por
Revisado por

NDz61rOWf_XldyuJlfY70wQMvGZBLNBUiiBEdQqTMcpGKzqWaoWqv49q8EgsmIkkjofkp501ywNyGjeDmhHeZIRut2zCZbxXC9RILMwwrbQkrKhn4LvtJKLtLmIb2C6iMsE9-QTo

Trabajar con variables de entorno es una gran manera de configurar diferentes aspectos de su aplicación Node.js. Muchos proveedores de servicios en la nube (Heroku, Azure, AWS, now.sh, etc.) y los módulos de Node.js utilizan variables de entorno. Los proveedores, por ejemplo, establecerán una variable PORT que especifica en qué puerto del servidor debe ubicarse para que funcione correctamente. Los módulos pueden tener diferentes comportamientos (como registrarse) en función del valor de la variable NODE_ENV

Éstos son algunos de mis trucos y herramientas cuando se trabaja con variables de entorno en Node.js.

Lo Básico

El acceso a las variables de entorno en Node.js es compatible desde el primer momento. Cuando el proceso Node.js se inicia, proporcionará automáticamente el acceso a todas las variables de entorno existentes mediante la creación de un objeto env  como una propiedad del objeto global process. Si quieres echar un vistazo a este objeto ejecute el REPL de Node.js con node en su línea de comandos y escriba:

console.log(process.env);

Este código debe ejecutar todas las variables de entorno de que es consciente el proceso Node.js. Para acceder a una variable específica, acceda a ella como con cualquier propiedad de un objeto:

console.log('The value of PORT is:', process.env.PORT);

Usted puede ver que el valor de PORT es undefined en su computador. Los proveedores de servicios en la nube, como Heroku o Azure, sin embargo, utilizan la variable PORT para decirle en qué puerto debe colocar su servidor para el enrutamiento funcione correctamente. Por lo tanto, la próxima vez que configure un servidor web, se debe determinar el puerto para escuchar, chequeando en primer lugar PORT y dándole un valor por defecto posteriormente:

const app = require('http').createServer((req, res) => res.send('Ahoy!'));
const PORT = process.env.PORT || 3000;

app.listen(PORT, () => {
  console.log(`Server is listening on port ${PORT}`);
}); 

La línea resaltada tomará el valor del PORT si está disponible o por defecto tomará 3000 como el valor del puerto de retorno para la escucha. Pruebe ejecutando el código guardándolo en un archivo como server.js y ejecute:

node server.js

La salida debe ser un mensaje que diga Server is listening on port 3000. Detenga  el servidor con Ctrl + C  y reinícielo con el siguiente comando:

PORT=9999 node server.js

El mensaje debe decir ahora Server is listening on port 9999  ya que la variable PORT se ha establecido temporalmente para esta ejecución por el PORT = 9999 en frente de node.

Ya que process.env es simplemente un objeto normal, podemos establecer / anular los valores muy fácilmente:

process.env.MY_VARIABLE = 'ahoy';

El código anterior establecerá  o anulará el valor de MY_VARIABLE. Sin embargo, tenga en cuenta que este valor sólo se establece durante la ejecución de este proceso Node.js y sólo está disponible en los procesos secundarios generados por este proceso. En general se debe evitar las variables de entorno primordiales tanto como sea posible, y en su lugar inicializar una variable de configuración como se muestra en el ejemplo PORT.

Explícitamente cargando variables desde archivos .env

Si usted desarrolla en un computador múltiples y diferentes proyectos Node.js, es posible encontrar que tiene superpuestos los nombres de las variables de entorno. Por ejemplo, diferentes aplicaciones de mensajería podrían necesitar diferentes SID del Servicio de Mensajería de Twilio, pero ambos se llamarían TWILIO_MESSAGE_SERVICE_SID. Una gran manera de lograr la configuración específica del proyecto es el uso de archivos .env . Estos archivos permiten especificar una variedad de diferentes variables de entorno y sus valores.

Normalmente, usted no desea comprobar estos archivos en el control de código fuente por lo que, cuando se crea uno debe añadir .env a su .git.ignore. Usted verá en una gran cantidad de aplicaciones de demostración de Twilio, archivos env.example que puede copiar a .env y establecer los valores por usted mismo. Tener un comando .env.example o un archivo similar es una práctica común si desea compartir una plantilla con otras personas en el proyecto.

¿Cómo cargar los valores de este archivo? La forma más sencilla es mediante el uso de un módulo de npm llamado dotenv. Basta con instalar el módulo a través de npm:

npm install dotenv --save

Luego añada la siguiente línea a la parte superior de su archivo de entrada:

require('dotenv').load();

Este código cargará automáticamente el archivo .env en la raíz de su proyecto e inicializará los valores. Se omitirá cualquier variable que ya haya sido establecida. No se debe utilizar archivos .env en su entorno de producción sino que debe establecer los valores directamente en respectivo servidor. Por lo tanto, es posible que desee envolver su comando de carga en una sentencia if-:

if (process.env.NODE_ENV !== 'production') {
  require('dotenv').load();
}

Con este código sólo se cargará el archivo .env si el servidor no se inicia en el modo de producción.

Vamos a ver esto en acción. Instale dotenv en un directorio como se muestra arriba. Cree un archivo dotenv-example.js en el mismo directorio y escriba las siguientes líneas en él:

console.log('No value for FOO yet:', process.env.FOO);

if (process.env.NODE_ENV !== 'production') {
  require('dotenv').load();
}

console.log('Now the value for FOO is:', process.env.FOO);

A continuación, cree un archivo llamado.env en el mismo directorio con el siguiente  contenido:

FOO=bar

Ejecute la secuencia:

node dotenv-example.js

La salida debe ser similar a:

No value for FOO yet: undefined
Now the value for FOO is: bar

Como se puede ver el valor se cargó y se definió utilizando dotenv. Si vuelve a ejecutar el mismo comando con NODE_ENV ajustado a production verá que permanecerá undefined.

NODE_ENV=production node dotenv-example.js

Ahora la salida debe ser:

No value for FOO yet: undefined
Now the value for FOO is: undefined

Si no desea modificar su código actual también se puede utilizar el argumento -r  de Node para cargar dotenv al ejecutar la secuencia de comandos. Cambie su archivo dotenv-example.js :

console.log('The value for FOO is:', process.env.FOO);

Ahora ejecute el archivo en primer lugar con normalidad:

node dotenv-example.js

La secuencia de comandos debe imprimir que el valor actual de FOO es undefined. Ahora ejecútelo con la bandera correspondiente a requerir dotenv:

node -r dotenv/config dotenv-example.js

El resultado es que FOO ahora se establece en bar ya que el archivo .env  se ha  cargado.

Si desea obtener más información sobre dotenv asegúrese de revisar esta documentación.

Una manera alternativa de cargar archivos .env

Sabemos que dotenv es muy bueno, pero había algo en particular que me molestó personalmente durante mi proceso de desarrollo. Este no anula a las variables .env existentes y usted no puede forzar  a que lo haga.

Como resultado de estas frustraciones, decidí escribir mi propio módulo basado en dotenv para solucionar este problema y hacer que las variables de entorno de carga cosas más convenientes. El resultado es node-env-run  o nodenv. Es una herramienta de línea de comandos que cargar un archivo .env inicializará los valores usando dotenv y luego ejecutará el script.

 

Se puede instalar globalmente pero recomiendo usarlo sólo con fines de desarrollo a nivel local y con el proyecto. Puede instalarlo ejecutando:

npm install node-env-run --save-dev

Después cree un archivo nodenv-example.js y coloque este código en él:

console.log('The value for FOO is:', process.env.FOO);

Como se puede ver, no se requiere nada aquí. Es sólo la aplicación lógica. En primer lugar trate de ejecutarlo utilizando node:

node nodenv-example.js

Este código ejecutado debería producir este comando The value for FOO is: undefined. Ahora trate de usar nodo-env-run mediante la ejecución de:

node_modules/.bin/nodenv nodenv-example.js

El resultado debe ser The value for FOO is: Bar  ya que cargó el archivo .env. El comando nodo-env-run puede anular los valores existentes. Para verlo en acción primero ejecute el siguiente comando:

FOO=foo node_modules/.bin/nodenv nodenv-example.js

La línea de comandos de salida debería decir The value for FOO is: foo. Si ahora permitimos el modo fuerza podemos anular los valores existentes:

FOO=foo node_modules/.bin/nodenv --force nodenv.js

Como resultado de ello deberíamos ver de nuevo el original The value for FOO is: Bar.

Si desea utilizar esta herramienta con regularidad, le recomiendo que lo envuelva en una secuencia de comandos de npm, añadiéndolo en el package.json al igual que:

{
  "name": "twilio-blog",
  "version": "1.0.0",
  "description": "",
  "main": "nodenv-example.js",
  "scripts": {
    "start": "node .",
    "start:dev": "nodenv -f ."
  },
  "author": "",
  "license": "ISC",
  "devDependencies": {
    "node-env-run": "^2.0.1"
  }
}

De esta manera usted puede simplemente ejecutar:

npm run start:dev

Si desea obtener más información sobre nodo-env-run  asegúrese de revisar su documentación.

Variables de entorno & secuencia de comandos npm

Hay escenarios en los que es útil para comprobar el valor de una variable de entorno antes de introducir la aplicación Node.js en las secuencias de comando de npm. Por ejemplo, si desea utilizar nodo-env-run cuando se encuentra en un entorno de desarrollo, pero node cuando se encuentre en modo de production. Una herramienta que hace esto es muy fácil es if-env. Puede instalarlo ejecutando:

npm install if-env --save

Asegúrese de no instalarlo como “dev dependency”, ya que vamos a exigir esto en la producción también.

Solo basta con modificar las secuencias de comandos npm en su package.json:

 "scripts": {
    "start": "if-env NODE_ENV=production ?? npm run start:prod || npm run start:dev",
    "start:dev": "nodenv -f .",
    "start:prod": "node ."
  }

Esta secuencia ejecutará ahora npm run start: prod   y posteriormente node. si NODE_ENV tiene el valor production, de lo contrario, se ejecutará npm run start:dev  y posteriormente nodenv -f..

Usted puede realizar esta técnica con cualquier otra variable de entorno también.

Pruébelo ejecutando:

# should output "The value of FOO is: bar"
npm start
# should output "The value of FOO is: undefined"
NODE_ENV=production npm start

Si desea obtener más información sobre if-env asegúrese de revisar su documentación.

Depurando

Todos sabemos en el momento que las cosas no están funcionando de la manera que desea, que algún módulo no está haciendo lo que tiene que hacer. Ese es el momento en que es hora para la depuración (debugging). Una estrategia que me ha ayudado mucho es el uso de la variable de entorno DEBUG para recibir registros más detallado de un grupo de módulos. Si, usted por ejemplo, toma un servidor básico express de la siguiente manera:

const app = require('express')();
const bodyParser = require('body-parser');
app.use(bodyParser.json()); // for parsing application/json
app.use(bodyParser.urlencoded({ extended: true })); // for parsing application/x-www-form-urlencoded

app.post('/', (req, res, next) => {
console.log(req);
});

app.listen(3000);

Y lo pone en marcha con el conjunto de variables DEBUG de*:

DEBUG=* node server.js

Usted recibirá un montón amplio  de registros que parece algo como esto:

La “magia” detrás de esto es un Módulo ligero llamado debug y su uso es muy fácil. Cuando usted desea utilizarlo todo lo que tiene que hacer es inicializar con un “espacio de nombres”. Después puede conectarse a ese espacio de nombres. Si alguien quiere ver los resultados  todo lo que tienen que hacer es habilitar el espacio de nombres en la variable DEBUG. El comando express en este caso utiliza un grupo de sub-espacios de nombres. Si usted quiere todo, desde el enrutador express, todo lo que tiene que hacer es configurar DEBUG con el comodín apropiado:

DEBUG=express:router* node server.js

Si desea utilizar debug en su propio módulo de todo lo que tiene que hacer es instalarlo primero:

npm install debug --save

Y después utilizarlo de la siguiente manera:

const debug = require('debug')('myApp:someComponent');

debug('Here is a pretty object %o', { someObject: true });

Si desea obtener más información sobre debug asegúrese de revisar su documentación.

Ahora puede utilizar todas las variables de entorno!

Estas no son, con mucho, todas las cosas que puede hacer con las variables de entorno y todas las herramientas que existen, sino más bien las que utilizo con más frecuencia. Si usted tiene alguna otra gran herramienta que utiliza con regularidad, me gustaría escuchar acerca de ellas!

Ahora que ha aprendido un poco más sobre las variables de entorno en Node.js, intente con Inicios rápidos en Node.js de Twilio!