Variáveis de Ambiente no NodeJS (.env)
Quando trabalhamos com desenvolvimento de software, na maioria das vezes, nós (desenvolvedores) precisamos armazenar certas chaves, tokens, códigos e expressões de forma estática dentro da nossa aplicação.
Como é o caso dos tokens de acesso de e-mail, chaves públicas ou privadas, uri de acesso ao banco de dados, usuário do banco de dados, senha do usuário do banco de dados, e muitos outros dados estáticos que não mudam.
Daí você pode me dizer assim: "Isso aí é fácil de ser resolvido, basta eu criar um arquivo de configuração, um JSON, ou quem sabe informar esses dados diretamente dentro das classes ou funções da minha aplicação".
E eu te respondo com um SIM, isso é totalmente possível, mas... será que vale a pena?
- Será que vale a pena armazenar credênciais diretamente nas classes/funções do seu código, ocasionando duplicação de credênciais?
- Será que vale a pena armazenar em arquivos em formato
JSON
, e sempre precisar chamar uma função capaz de decodificar, e ler este arquivo? - Será que vale a pena salvar em um
config.js
, e fazer com que a lógica de acesso a credênciais fique presa a linguagem Javascript?
Ou será que vale mais a pena salvar todos esses dados em um arquivo que pode ser lido de forma automática pela maioria das linguagens, bibliotecas e frameworks?
Sim, eu estou me referindo ao arquivo .env
, que por sinal, iremos aprender agora sobre ele 🤓
O que são variáveis de ambiente
Variáveis de Ambiente é o nome que se dá para os arquivos que armazenam informações (credênciais estáticas) importantes, e que ficam disponíveis para que a sua aplicação possa acessá-las em qualquer lugar.
Você sabe o que os maiores frameworks do desenvolvimento web (NodeJS, Laravel, ReactJS, NextJS, NestJS, Vue...) tem em comum?
Todos eles possuem suporte a leitura de arquivos .env
, que nada mais são do que arquivos que armazenam em uma estrutura de chave e valor, todas as informações que a nossa aplicação precisa consultar (famosas variáveis de ambiente).
Em toda a nossa aplicação, o ideal é que você tenha apenas um único arquivo chamado .env
dentro da pasta raiz da sua aplicação, de resto, os outros arquivos são apenas variações...
Essa variável acaba se tornando uma peça chave fundamental durante o desenvolvimento das suas aplicações em NodeJS 😉
Por que usar variáveis de ambiente?
Vamos supor que você tenha uma chave de acesso que será usada por uma API durante a sua aplicação:
Autorization Key: FF908-98UIO-KK97
Vamos supor também, que em diferentes partes do seu código, você precisa acessar essa chave de acesso. Então vamos imaginar que temos 5 classes que fazem o uso dessa chave dentro da nossa aplicação:
Dashboard
Usuarios
Produtos
Servicos
Configuracoes
Cada qual fazendo uma chamada em um endpoint diferente de uma mesma API, como por exemplo:
/getDashboardData
/getUsuarios
/getProdutos
/getServicos
/getConfiguracoes
Como em cada endpoint você precisa passar a sua chave de acesso (Autorization Key) no header
da sua requisição, você pode enviá-la de algumas formas diferentes:
- Você pode inserir essa chave na chamada de cada endpoint.
- Você pode salvar essa chave na memória, e passá-la para cada uma das suas classes ou funções.
- Você pode criar um
config.js
para armazenar essa chave.
Apesar de todas as estratégias acima funcionrem muito bem, por motivos óbvios (e já explicados anteriormente), é claro que a melhor opção seria a criação de um arquivo .env
, pelos seguintes motivos:
Segurança: usar arquivos .env
, vai manter a sua chave fora do código-fonte, evitando exposição acidental em repositórios públicos. (uma vez que o arquivo .env não costuma subir para a nuvem)
Manutenção: manter arquivos .env
, vai facilita a atualização da chave sem modificar o código, apenas alterando o arquivo .env
. (ou seja, você não precisa mexer nos arquivos do código, e ficar procurando pelas linhas que precisam ser alteradas).
Flexibilidade: graças aos arquivos .env
, você consegue criar diferentes configurações para ambientes diversos (desenvolvimento, produção), sem a necessidade de mudar o seu código.
Colaboração: outros desenvolvedores (colaboradores) podem ter suas próprias chaves configuradas localmente, sem a necessidade de expor uma chave em comum. (As vezes um desenvolvedor pode ter um token diferente de outro...)
Boas Práticas: por fim, o uso do arquivo .env
segue o padrão da indústria para o gerenciamento de variáveis sensíveis. (sim, a maioria dos projetos usam esses arquivos para armazenar credênciais, logo, você também precisa aprender sobre eles se quer entrar no mercado de trabalho)
Tipos de variáveis de ambiente
No mundo das variáveis de ambiente, nós podemos separá-la em duas grandes categorias:
- Variáveis de Ambiente definidas pelo sistema,
- Variáveis de Ambiente definidas pelo usuário.
Veremos a diferença entre cada uma delas no próximo tópico 😆
Variáveis de Ambiente definidas pelo sistema
Esses tipos de variáveis são predefinidas pela sua aplicação em questão, como as variáveis PATH
, HOME
, PORT
, que são mais comuns em sistemas operacionais Unix/Linux, e geralmente não são acessíveis diretamente pelo JavaScript em um ambiente de navegador.
Elas nada mais são que "configurações padrão" do seu sistema, ajudando a orientar suas aplicações sobre como procurar determinadas coisas ou caminhos.
No caso do NodeJS, podemos acessá-las por meio do comando process.env.NOME_DA_VARIAVEL
.
Variáveis de Ambiente definidas pelo usuário
Quando me refiro ao usuário, estou me referindo a você DESENVOLVEDOR, responsável por dar a vida a sua aplicação.
É aqui que entra o famoso arquivo .env
, onde podemos declarar qualquer tipo de informação desde um número de porta, um segredo e até mesmo uma chave de API.
Elas serverm como post-its pessoais que nos ajudam a armazenar dados de forma global por toda a nossa aplicação.
Dito isso, vamos colocar a mão na massa com o NodeJS 😉
Criando nosso projeto de testes
Antes de colocarmos a mão na massa, é deveras importante que você configure o seu projeto inicial.
Para isso, eu criei uma pasta chamada de VariaveisDeAmbiente dentro da minha área de trabalho (desktop):
Com o seu terminal (Prompt de Comando) aberto na pasta raiz que acabamos de criar, precisamos inicializar o nosso projeto por meio do NPM
, sendo assim, execute o seguinte comando abaixo:
npm init -y
A flag -y
, como você já deve saber, cria um novo projeto de forma enxuta, respondendo SIM para tudo 😅
Por fim, não se esqueça de criar seu index.js
, com uma mensagem bem legal de boas vindas:
console.log('Olá Mundo!');
Criando sua variável de ambiente
A primeira etapa consiste em criar um arquivo chamado de .env
dentro da pasta raiz do seu projeto:
E não, atualmente o NPM
não cria de forma padrão esse tipo de arquivo pra gente, repassando tal função para nós, meros desenvolvedores 😅
Observação: quando usamos frameworks tais como Laravel
, NextJS
e alguns outros, esses arquivos são criados de forma automática pelo sistema.
Definindo suas variáveis de ambiente
Agora que você já sabe como criar o arquivo, basta abrir o arquivo .env
e começar a criar suas chaves, no meu caso eu criei 5:
NOME=micilini
RANK=100
SECRET="Micilini é DEZ!"
KEY="@090OALK''JJ3"
SITE_APP=https://micilini.com/
Note que todas as chaves estão usando o operador de atribuição (=
) e definindo seus valores, onde cada um deles estão sendo separados por uma quebra de linha.
Note também que podemos definir nossas chaves dentro de aspas duplas, o que representa uma string de fato (Observação: isso não é recomendado, mas funciona em alguns casos).
Instalando a biblioteca dotenv
O NodeJS não possui suporte nativo direto para ler arquivos .env
🥲
Embora ele possa acessar variáveis de ambiente do sistema usando process.env
, ele não consegue carregar automaticamente um arquivo .env
sem uma biblioteca externa.
Por isso, precisamos utilizar uma biblioteca super conhecida chamada de dotenv
.
Sendo assim, com o seu terminal (Prompt de Comando) aberto na pasta raiz do seu projeto, basta executar o seguinte comando:
npm install dotenv
Após instalado, podemos prosseguir adiante.
Usando suas variáveis de ambiente
O uso dessas variáveis é tão simples quando chamar um objeto em Javascript, observe um exemplo das chaves sendo chamadas dentro do arquivo index.js
:
// Carrega o arquivo .env
require('dotenv').config();
// Acessando as variáveis
console.log(process.env.NOME); // micilini
console.log(process.env.RANK); // 100
console.log(process.env.SECRET); // Micilini é DEZ!
console.log(process.env.KEY); // @090OALK''JJ3
console.log(process.env.SITE_APP); // https://micilini.com/
Note que chamamos a biblioteca dotenv
(que acabamos de instalar), junto com o método config
, que é responsável por carregar suas variáveis que estão no arquivo .env
, para dentro do ambiente do NodeJS, tornando-as acessíveis através do objeto process.env
.
Trabalhando com variáveis de ambiente em diferentes ambientes
Em tópicos anteriores foi dito que nós podemos definir diversas variáveis de ambiente em diferentes tipos de ambiente, como ambiente de desenvolvimento, de testes e produção.
Mas como isso funciona na prática? Simples, você pode criar diversos arquivos .env
com nomes especificos, por exemplo:
.env
(Padrão da aplicação).env.example
(Arquivo de exemplo, com chaves vazias).env.local
(Este arquivo é carregado para todos os ambientes, exceto teste.).env.development
(Este arquivo é carregado em ambientes de desenvolvimento).env.test
(Este arquivo é carregado em ambientes de testes).env.production
(Este arquivo é carregado em ambientes de produção)
O carregamento de cada um desses arquivos depende da biblioteca dotenv-flow
(ensinaremos mais sobre ela mais tarde).
Vamos ver um exemplo prático entre algumas diferenças dos arquivos .env
:
.env.production
:
REACT_APP_API_BASE_URL=https://api.producao.com/
.env.development
:
REACT_APP_API_BASE_URL=https://api.desenvolvimento.com/
Quando sua aplicação estiver em modo de desenvolvimento ou produção, o NodeJS junto com o dotenv-flow
irá escolher automaticamente qual arquivo que será carregado
Existem ainda aquelas aplicações que possuem um arquivo chamado de .env.example
, que representa um exemplo de quais chaves deverão ser setadas dentro de um arquivo .env
:
REACT_APP_NOME=
REACT_APP_RANK=
REACT_APP_SECRET=
REACT_APP_KEY=
REACT_APP_SITE=
Note que as chaves estão atreladas a valores vazios, pois o objetivo desse arquivo é apenas instruir o desenvolvedor sobre quais variáveis o sistema precisa para rodar.
Instalando e usando o dotenv-flow
Para gerenciar o carregamento correto desses arquivos .env
em diferentes ambientes, você pode usar o pacote dotenv
em conjunto com o pacote dotenv-flow
, que automaticamente carrega os arquivos conforme o ambiente.
Sendo assim, com o terminal (Prompt de Comando) aberto na pasta raiz da sua aplicação, execute o comando abaixo:
npm install dotenv-flow
Já no seu index.js
, basta chamar suas chaves da seguinte forma:
require('dotenv-flow').config();
console.log(process.env.API_URL); // Variável será carregada conforme o ambiente
O dotenv-flow
sabe qual ambiente você está através da variável de ambiente NODE_ENV
.
O NODE_ENV
é uma variável padrão em aplicações NodeJS que indica o ambiente em que a aplicação está rodando, como development
, production
, test
, etc.
E para mudar o valor dessa variável é bem simples, basta rodar a sua aplicação usando os seguintes comandos no terminal:
Para ambiente de desenvolvimento (carrega o .env.development):
NODE_ENV=development node index.js
Para ambiente de testes (carrega o .env.test):
NODE_ENV=test node index.js
Para ambiente de produção (carrega o .env.production):
NODE_ENV=production node index.js
Caso desejar, você pode alterar o package.json
para executar esses ambientes de forma automática, observe:
{
"scripts": {
"start": "NODE_ENV=production node index.js",
"dev": "NODE_ENV=development node index.js",
"test": "NODE_ENV=test node index.js"
}
}
Com isso, basta apenas executar no terminal:
npm run dev # Para o ambiente de desenvolvimento
npm run start # Para o ambiente de produção
npm run test # Para o ambiente de testes
A verdade é que quando o NodeJS for executado via terminal em conjunto com o comando NODE_ENV
, por de baixo dos panos, essa variável vai ficar salva de forma global na sua aplicação, o que influência diretamente o arquivo que será carregado pela biblioteca dotenv-flow
.
Criando variáveis de ambiente de uma maneira saudável
Para criar uma aplicação organizada, saudável e de fácil manutenção, você precisa mapear suas variáveis de ambiente com nomes legíveis e sempre em letras maiúsculas.
Dê nomes descritivos às suas variáveis de ambiente e que fazem sentido não só pra você, quanto também para outros desenvolvedores que irão trabalhar em cima do seu código.
Por exemplo, se você estiver usando uma API voltada para uma aplicação de restaurante, em vez de mapear a sua váriavel como API_KEY
, opte por um nome mais especifico e legível como: RESTAURENT_API_KEY
.
Uma outra boa prática está relacionado ao não adiconamento de strings ou caracteres que possuam espaço em seus valores, como por exemplo:
// Evite isso
API_KEY="12345"
SECRET="oim 92m3d 29nd2 nd9d"
// Faça isso em vez disso
API_KEY=12345
SECRET=oim92m3d29nd2nd9d
É importante ressaltar que os valores existentes dentro dos arquivos .env
são tratados como strings, portanto, se você colocar seus valores entre aspas (sejam elas duplas ou simples) ou quem saber inserir espaços em branco, tais valores podem gerar resultados inesperados e bugs difíceis de rastrear.
Vai por mim, experiência própria...
Importante: Não faça o upload de arquivos .env para repositórios online
Sim, é isso mesmo que você leu!
Arquivos .env
costumam ter informações sensíveis, tanto é que no arquivo .gitignore
do Git, por padrão tais arquivos NÃO devem ser upados para repositorios públicos ou privados.
Sendo assim, antes de realizar um GIT PUSH ou um PULL REQUEST, certifique-se de que o arquivo .env
não está sendo enviado também. (muito menos o .env.development, .env.test, .env.production... o .env.example pode passar)
Beleza... então como eu faço para enviar o arquivo .env
, uma vez que a minha aplicação depende dele?
Se você trabalha com um time de desenvolvimento, sempre passe esses arquivos de maneira segura (e-mail, slack ou qualquer outro canal de segurança) entre vocês.
Se é você quem coloca sua aplicação online, evite incluir o envio desse arquivo diretamente em técnicas de CI/CD, opte por fazer o upload na pasta raiz do seu projeto de maneira manual.
Como alternativa você pode enviar o arquivo .env.example
em reposirórios online, para que os futuros devs ou arquitetos que forem clonar o seu repositorio, tenham uma ideia de quais variáveis de ambiente a sua aplicação necessite para rodar.
Arquivos da lição
Os arquivos que você viu durante o decorrer desta lição, podem ser encontrados neste link.
Conclusão
Nesta lição, você aprendeu um pouco mais sobre o uso das variáveis de ambiente 😎
Até a próxima.