process.env é um objeto com uma propriedade para cada variável de ambiente que o shell passou para o seu programa Node.js: process.env.PORT, process.env.DATABASE_URL e assim por diante. Uma variável que não foi definida vem como undefined, e uma variável definida é sempre string. Leia uma vez na inicialização, dê um valor padrão e converta para o tipo de que você precisa.
Ele imprimiu shop on port 8080 in eu-west (REGION nunca foi definida, então o valor padrão entrou), depois string number: a variável é texto até Number() convertê-la. Apague as duas primeiras atribuições e rode de novo para ver todos os valores padrão.
Defina variáveis de ambiente no shell
As variáveis vêm de onde o Node.js é iniciado. Em um terminal:
// macOS and Linux: for one command
PORT=8080 NODE_ENV=production node app.js
// macOS and Linux: for the rest of the terminal session
export PORT=8080
// Windows PowerShell
$env:PORT = "8080"; node app.js
// Windows cmd.exe
set PORT=8080
node app.js
Plataformas de hospedagem (Heroku, Render, Vercel, Docker, Kubernetes) têm uma página de configurações ou um arquivo para a mesma coisa; seu código lê do mesmo jeito.
Tudo é string
É daqui que vem a maioria dos bugs com process.env. 'false' e '0' são strings não vazias, então são truthy:
A verificação ingênua imprimiu debug is ON para uma variável com valor false, então compare com a string exata que você espera. Para números, Number(process.env.X) transforma um valor ausente em NaN, então aplique o padrão antes de converter, como o primeiro exemplo fez com ??.
NODE_ENV
NODE_ENV é uma convenção, não um recurso do Node.js: o Node.js nunca define essa variável. Quem lê são as bibliotecas. O Express, por exemplo, esconde stack traces das páginas de erro quando ela é production, e muitas ferramentas pulam verificações que só servem em desenvolvimento.
Ele imprimiu mode: production e verbose logs: false; troque 'production' por 'development' e a segunda linha se inverte. Use só production, development e test, porque as bibliotecas procuram exatamente essas palavras.
Arquivos .env: --env-file e dotenv
Digitar todas as variáveis antes de node cansa. Um arquivo .env guarda essas variáveis na pasta do projeto, uma por linha:
// .env
PORT=8080
DATABASE_URL=postgres://localhost/shop
API_KEY=dev-key-123
O Node.js 20.6 em diante lê esse arquivo com uma flag, sem pacote nenhum:
node --env-file=.env app.js
Em versões mais antigas, ou se você preferir, instale o pacote dotenv (npm install dotenv) e carregue no topo do arquivo de entrada, antes de qualquer código ler process.env:
require('dotenv').config(); // copies .env into process.env
console.log(process.env.PORT); // 8080
Nenhum dos dois sobrescreve uma variável que já está definida no shell, então as configurações de produção prevalecem sobre o arquivo.
Falhe cedo quando faltar variável
Uma URL de banco de dados ausente deve parar o programa na inicialização com uma mensagem clara, não derrubá-lo na primeira requisição uma hora depois:
Ele imprimiu Missing environment variables: API_KEY; adicione process.env.API_KEY = 'test'; no topo e ele imprime Config OK. Em um programa real, depois da mensagem chame process.exit(1), porque um código de saída diferente de zero é como um script de deploy ou uma plataforma de containers percebe que a inicialização falhou.
Nunca faça commit de segredos
Coloque .env no .gitignore no mesmo dia em que criar o arquivo. Faça commit de um .env.example com os nomes das variáveis e valores falsos, para os outros saberem o que configurar. Uma chave que já foi enviada para um repositório deve ser tratada como vazada e trocada, mesmo que você apague o commit depois.
Perguntas frequentes
Por que process.env.MY_VAR é undefined?
A variável não foi definida no shell que iniciou o Node.js, ou foi definida em outro terminal. Um arquivo .env também não é lido automaticamente: inicie o Node.js com --env-file=.env ou carregue com dotenv antes de ler o valor.
Posso alterar process.env com o programa rodando?
Sim. Atribuir process.env.X = 'value' muda o valor para o processo atual e para qualquer processo filho que ele iniciar depois, mas nunca para o shell que abriu o Node.js. O Node.js converte o valor atribuído em string.
Nomes de variáveis de ambiente diferenciam maiúsculas e minúsculas?
No Linux e no macOS, sim: PORT e port são duas variáveis. No Windows, não. Use nomes em maiúsculas com underscore e essa dúvida nunca aparece.
O navegador consegue ler process.env?
Não. Navegadores não têm variáveis de ambiente. Ferramentas de build como Vite e Next.js copiam variáveis selecionadas para o seu código frontend no build, o que também significa que esses valores ficam públicos.