Trabalhar com variáveis de ambiente em Node.js

February 10, 2022
Escrito por
Revisado por

Com apenas algumas linhas de código, você pode executar um aplicativo Node.js diretamente do terminal e usar a Twilio para enviar e receber mensagens de texto com o Twilio Programmable SMS.

Fundamentos das variáveis de ambiente em Node.js

Node.js é uma das estruturas mais comentadas na comunidade de desenvolvimento da Web desde Rails. Embora ainda seja muito jovem, o Node.js provou ser rápido, altamente escalável e eficiente. O motivo disso é devido à sua estrutura de entrada/saída sem bloqueio orientada por eventos.

A combinação com o Twilio ajuda você a criar aplicativos de telefonia em poucas etapas. No entanto, se você quiser enviar um SMS, por exemplo, será necessário instalar o Node.js e o módulo Twilio Node.js.

Outro grande recurso da linguagem Node.js (e seus módulos) é que ela tem uma maneira de trabalhar com variáveis de ambiente, que muitos hosts de nuvem (como Heroku, Azure, AWS, Now.sh etc.) usam. Isso proporciona uma série de maneiras de configurar diferentes aspectos do aplicativo Node.js. Portanto, enquanto os hosts definirão uma variável PORT que especifica a qual porta o servidor deve ouvir, os módulos podem ter comportamentos diferentes (como registro em log) dependendo do valor da variável NODE_ENV.

Neste blog, revisaremos alguns truques e ferramentas ao trabalhar com variáveis de ambiente no Node.js.

Em primeiro lugar, precisamos garantir que tenhamos um ambiente Node.js. Em seguida, vamos guiar você pelos fundamentos da configuração do Node.js para uso com o Twilio em um Mac. Isso incluirá a instalação do npm em um Mac e a preparação do ambiente para um projeto Twilio.

Como verificar se o Node.js está instalado

Você pode verificar se já tem o Node.js instalado em sua máquina abrindo um terminal e executando o seguinte:

node -v

Se você não tiver o Node.js instalado, as etapas a seguir mostrarão como instalá-lo: 

  1. Vá para a página de downloads do Node.js.
  2. Clique na opção "Macintosh Installer" para baixar o Node.js para macOS.
  3. Execute o instalador do Node.js .pkg baixado.
  4. Execute o instalador, aceite a licença, selecione o destino e autentique para a instalação.

Depois que o instalador estiver concluído, você poderá garantir que o Node.js executará "node -V" em seu terminal. Você deverá obter o número da versão atual, conforme mostrado acima. 

Se a versão do Node.js instalado não for exibida, talvez seja necessário reiniciar o terminal.

Para garantir que a instalação esteja correta e executando o "npm -V", procure uma confirmação da instalação por meio da versão.

Agora o ambiente Mac está pronto para instalar o módulo Twilio para que os scripts Node.js no diretório atual possam usá-lo.

Carregamento explícito de variáveis de arquivos .env 

Você pode acessar variáveis de ambiente no Node.js imediatamente. Quando o processo Node.js é inicializado, ele automaticamente fornece acesso a todas as variáveis de ambiente existentes ao criar um objeto "env" dentro do objeto global do processo. 

Se quiser dar uma olhada no objeto, execute o Node.js REPL com "node" na linha de comando e digite:

console.log(process.env);

Esse código deve gerar todas as variáveis de ambiente que esse processo Node.js pode coletar. Para acessar uma variável específica, acesse-a como faria com qualquer propriedade de um objeto:

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

Aqui, você notará que o valor de PORT está indefinido no seu computador. No entanto, hosts de nuvem, como Heroku ou Azure, usam a variável PORT para informar a qual porta seu servidor deve ouvir para que o roteamento funcione corretamente. Assim, na próxima vez que configurar um servidor da Web, você poderá determinar a porta a ser ouvida marcando a PORT primeiro e fornecendo um valor padrão depois:

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}`);
});

A linha realçada usará o valor de PORT se estiver disponível ou definirá o padrão 3000 como uma porta de fallback. Para tentar executar o código, salve-o em um arquivo como server.js e execute:

node server.js

A saída deve ser uma mensagem dizendo "Server is listening on port 3000." Pare o servidor com Ctrl+C e reinicie-o com o seguinte comando:

PORT=9999 node server.js

A mensagem agora deve dizer: "Server is listening on port 9999." Isso significa que a variável PORT foi temporariamente definida na frente do nó para essa execução por PORT=9999. 

Como process.env é um objeto normal, podemos definir/substituir os valores:

process.env.MY_VARIABLE = 'ahoy';

O código acima definirá ou substituirá o valor de MY_VARIABLE. No entanto, lembre-se de que esse valor só é definido durante a execução desse processo Node.js e só está disponível em processos filhos gerados por esse processo. Em geral, você deve evitar a substituição das variáveis de ambiente o máximo possível e apenas inicializar uma variável de configuração, como mostrado no exemplo de PORT.

Se você desenvolver vários projetos Node.js em um computador, poderá ter nomes de variáveis ​​de ambiente sobrepostos. Por exemplo, diferentes aplicativos de mensagens podem precisar de diferentes SIDs do Twilio Messaging Service, mas ambos seriam chamados TWILIO_MESSAGE_SERVICE_SID. Uma ótima maneira de obter uma configuração específica do projeto é usar arquivos .env. Esses arquivos permitem especificar várias variáveis de ambiente e valores associados.

Normalmente, você não quer fazer o check-in desses arquivos no controle de origem. Assim, ao criar um, basta adicionar .env ao seu arquivo .gitignore. Com muitos arquivos .env.example dos aplicativos de demonstração da Twilio, é possível copiá-los para arquivos .env e definir os valores você mesmo. Ter um arquivo .env.example ou similar é uma prática comum se você quiser compartilhar um arquivo de modelo com outras pessoas no projeto.

Como carregamos os valores deste arquivo? A maneira mais rápida é usar um módulo npm chamado dotenv. Instale o módulo via npm:

npm install dotenv --save

Depois, adicione a seguinte linha à parte superior do arquivo de entrada:

require('dotenv').config();

Esse código carregará automaticamente o arquivo .env na raiz do projeto e inicializará os valores, ignorando todas as variáveis já predefinidas. Tenha cuidado para não usar arquivos .env em seu ambiente de produção. Em vez disso, defina os valores diretamente no respectivo host. Você pode querer finalizar sua instrução de carga em uma instrução if:

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

Com esse código, só carregaremos o arquivo .env se o servidor ainda não estiver no modo de produção.

Vamos ver isso na prática. Instale dotenv em um diretório, conforme mostrado acima. Em seguida, crie um arquivo dotenv-example.js no mesmo diretório e coloque as seguintes linhas nele:

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

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

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

Depois, crie um arquivo chamado .env no mesmo diretório com este conteúdo:

FOO=bar

Execute o script:

node dotenv-example.js

A saída deve ser semelhante a:

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

Como você pode ver, o valor foi carregado e definido usando "dotenv". Se você executar novamente o mesmo comando com NODE_ENV definido para produção, verá que ele permanecerá indefinido.

NODE_ENV=production node dotenv-example.js

Agora, a saída deve ser:

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

Se você não quiser modificar seu código real, também poderá usar o argumento -r do Node para carregar dotenv ao executar o script. Para fazer isso, altere seu arquivo dotenv-example.js para:

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

Agora execute o arquivo como você normalmente faria:

node dotenv-example.js

O saída do script deve mostrar que o valor atual para FOO é undefined. Agora, execute-o com o sinalizador apropriado para solicitar dotenv:

node -r dotenv/config dotenv-example.js

O resultado é que FOO agora está definido como bar desde que o arquivo .env foi carregado. Se quiser saber mais sobre dotenv, consulte a documentação.

Uma maneira alternativa de carregar arquivos .env

Há também um módulo alternativo baseado em "dotenv" para tornar as variáveis do ambiente de carregamento mais convenientes. O resultado é node-env-run ou nodenv. Esta ferramenta de linha de comando carregará um arquivo .env, inicializará os valores usando o "dotenv" e executará seu script.

Você pode instalá-la globalmente, mas isso é recomendado apenas para fins de desenvolvimento e localmente para o projeto. Para instalá-la, execute:

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

Depois, crie um arquivo nodenv-example.js e coloque este código nele:

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

Como você pode ver, não precisamos solicitar nada aqui porque é apenas a lógica do aplicativo. Para tentar executá-lo, use o nó:

node nodenv-example.js

Esse código executado deve gerar a mensagem "The value for FOO is: undefined." Agora, tente usar node-env-run executando:

node_modules/.bin/nodenv nodenv-example.js

O resultado deve ser "The value for FOO is: bar", pois carregou o arquivo .env.

O uso de node-env-run pode substituir esses valores existentes. Para vê-lo na prática, primeiro execute o seguinte comando:

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

A saída da linha de comando deve dizer: "The value for FOO is: foo." Se agora ativarmos o modo de força, poderemos substituir os valores existentes:

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

Como resultado, devemos voltar ao original "The value for FOO is: bar."

Se você quiser usar essa ferramenta regularmente, recomendo que você a envolva em um script npm adicionando-a no package.json assim:

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

Dessa forma, você pode executar:

npm run start:dev

Se quiser saber mais sobre node-env-run, consulte a documentação.

Variáveis de ambiente e scripts npm

Há também cenários em que é útil verificar o valor de uma variável de ambiente antes de inserir o aplicativo Node.js em scripts npm. Por exemplo, se você quiser usar node-env-run quando estiver em um ambiente de desenvolvimento, mas usar node quando estiver no modo de produção. Use a ferramenta if-env para isso. Para instalá-la, execute:

npm install if-env --save

No entanto, certifique-se de não instalá-la como uma "dependência dev", pois também solicitaremos isso na produção.

Agora, modifique seus scripts npm no package.json:

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

Este script executará agora "npm run start:prod" e, subsequentemente, "node". Se NODE_ENV tiver o valor "production", ele poderá executar "npm run start:dev" e, subsequentemente, "nodenv -f". Você também pode fazer isso com qualquer outra variável de ambiente.

Para testar, execute:

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

Se quiser saber mais sobre if-env, consulte a documentação.

Como instalar o npm em um Mac

Normalmente, isso será instalado automaticamente como parte da instalação acima. Você pode verificar isso executando o comando "npm" no terminal. Se tiver instalado, você verá uma lista de uso. Caso contrário, para instalar o npm, execute o seguinte: 

sudo apt install npm

Depuração em Node.js

A próxima questão é o tempo de depuração. Uma estratégia que me ajudou muito é usar a variável de ambiente DEBUG para receber registros mais detalhados para vários módulos. Tome como exemplo um servidor básico expresso como este:

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);

Inicie-o com a variável DEBUG definida como *:

DEBUG=* node server.js

Você receberá um registro extenso que se parece com isto:

A magia por trás disso é um módulo leve chamado debug. Quando quiser usá-lo, tudo o que você precisa fazer é inicializá-lo com um namespace. Depois, você pode registrá-lo nesse namespace. Se alguém quiser ver a saída, tudo o que precisa fazer é ativar o namespace na variável DEBUG. Nesse caso, "express" usa vários subnamespaces. Portanto, se quiser tudo a partir do roteador expresso, você precisa definir DEBUG com o curinga apropriado:

DEBUG=express:router* node server.js

Se quiser usar o debug em seu módulo, primeiro é necessário instalá-lo:

npm install debug --save

Depois, aplique-o da seguinte maneira:

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

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

Se quiser saber mais sobre debug, consulte a documentação.

Use todas as variáveis de ambiente Node.js em Node.js com a Twilio

Estas são apenas algumas coisas que você pode fazer com variáveis de ambiente e todas as ferramentas que existem. Agora que você já aprendeu um pouco mais sobre as variáveis de ambiente em Node.js, experimente os Inícios rápidos do Node.js da Twilio, incluindo nosso Início rápido do SMS. Comece a usar gratuitamente!