Carregar variáveis de um arquivo .env é tão comum que o pacote dotenv virou dependência quase obrigatória em projetos Node.js. Hoje o próprio runtime faz isso: a flag --env-file carrega o arquivo antes da aplicação iniciar, e a função process.loadEnvFile() faz o mesmo de dentro do código, sem instalar nada.
O jeito antigo
Com o dotenv, o primeiro passo de toda aplicação era instalar o pacote e chamá-lo antes de qualquer outro import que dependesse das variáveis:
// npm install dotenv
import 'dotenv/config';
console.log(process.env.DATABASE_URL);
Funciona, mas é mais uma dependência para manter atualizada e auditar, e a ordem dos imports vira uma armadilha: qualquer módulo carregado antes do dotenv não enxerga as variáveis.
--env-file: variáveis carregadas antes do código
Com a flag --env-file, o Node lê o arquivo e popula process.env antes de executar a primeira linha da aplicação. Dado este .env:
# .env
PORT=3000
DATABASE_URL="postgres://app:segredo@localhost:5432/loja"
export LOG_LEVEL=debug # o "export" no início é ignorado
basta apontar o arquivo na linha de comando:
node --env-file=.env server.js
// server.js
import http from 'node:http';
const porta = Number(process.env.PORT);
http.createServer((req, res) => {
res.end(`Nível de log: ${process.env.LOG_LEVEL}`);
}).listen(porta, () => console.log(`Rodando na porta ${porta}`));
O formato aceita comentários com #, valores entre aspas simples, duplas ou crases, o prefixo export e valores de múltiplas linhas entre aspas.
Vários arquivos e arquivos opcionais
A flag pode ser repetida. Arquivos posteriores sobrescrevem variáveis definidas pelos anteriores, o que facilita ter uma base comum e um ajuste por ambiente:
node --env-file=.env --env-file=.env.local server.js
Se o arquivo não existir, --env-file encerra com erro. Para arquivos que podem ou não estar presentes — como um .env.local que só existe na máquina de quem desenvolve — use --env-file-if-exists:
node --env-file=.env --env-file-if-exists=.env.local server.js
Um detalhe importante: se a mesma variável já existir no ambiente do processo (definida pelo shell, pelo Docker ou pela plataforma de deploy), o valor do ambiente vence o do arquivo. Assim, o .env serve de valor padrão e a produção pode sobrescrevê-lo sem mexer em nada.
process.loadEnvFile(): carregando de dentro do código
Quando não dá para controlar a linha de comando — por exemplo, num script chamado por outra ferramenta — process.loadEnvFile() carrega o arquivo em tempo de execução. Sem argumentos, ele lê o .env do diretório atual:
// migrar.js
if (process.env.NODE_ENV === 'test') {
process.loadEnvFile('./.env.test'); // carregado primeiro, tem prioridade
}
process.loadEnvFile(); // completa com o que faltar do ./.env
console.log(`Migrando o banco ${process.env.DATABASE_URL}`);
Assim como a flag, process.loadEnvFile() não sobrescreve variáveis que já existem em process.env — nem as do ambiente, nem as carregadas por uma chamada anterior. Por isso a ordem importa: no exemplo, o .env.test é carregado antes, e o .env só preenche as variáveis que ainda faltam.
Para apenas interpretar o conteúdo sem tocar em process.env, existe util.parseEnv(), que transforma o texto de um .env em um objeto:
import { parseEnv } from 'node:util';
const vars = parseEnv('API_URL=https://api.exemplo.com\nTIMEOUT=5000');
console.log(vars); // { API_URL: 'https://api.exemplo.com', TIMEOUT: '5000' }
Usando no package.json
{
"scripts": {
"dev": "node --watch --env-file=.env --env-file-if-exists=.env.local server.js",
"start": "node --env-file-if-exists=.env server.js"
}
}
No script start, o --env-file-if-exists permite que o mesmo comando funcione em produção, onde as variáveis normalmente vêm da plataforma e não existe .env.
Quando usar
- Remover o
dotenvde projetos que só precisavam dele para ler um.env. - Separar configurações por ambiente com vários arquivos (
.env,.env.local,.env.test). - Scripts de manutenção e migrações que precisam das mesmas variáveis da aplicação.
- Configurar o próprio Node via
NODE_OPTIONSdentro do.env, já que a flag também aplica essas variáveis.
Cuidados
O suporte nativo cobre a leitura do arquivo, mas não recursos extras de bibliotecas como dotenv-expand, como referenciar uma variável dentro de outra (${HOST}:${PORT}). Continue mantendo o .env fora do controle de versão e lembre que todos os valores chegam como string — converta números e booleanos explicitamente.
Compatibilidade
A flag --env-file chegou no Node.js 20.6.0. process.loadEnvFile() e util.parseEnv() vieram no Node.js 21.7.0, com backport para o 20.12.0, e --env-file-if-exists no Node.js 22.9.0. As flags --env-file e --env-file-if-exists deixaram de ser experimentais no Node.js 24.10.0 e 22.21.0.
Conclusão
Com --env-file, --env-file-if-exists e process.loadEnvFile(), o Node.js resolve sozinho o que antes exigia o dotenv. A regra de que o ambiente sempre vence o arquivo deixa o mesmo código funcionar no desenvolvimento e em produção, com uma dependência a menos para manter.
0 Comentário
Deixe seu Comentário!
Dúvida, sugestão ou só um "valeu!" — tudo é bem-vindo por aqui.