Переменные окружения: dotenv
dotenv — библиотека для загрузки переменных окружения из файла .env в process.env, позволяющая хранить конфигурацию (ключи API, строки подключения к БД) вне кода и отдельно для каждого окружения.
Зачем нужно
Хардкодинг секретов (паролей, API-ключей) в коде — угроза безопасности: они попадают в git-историю и видны всей команде. Переменные окружения разделяют конфигурацию и код: разные значения в development, staging, production при одном и том же коде. .env файл добавляется в .gitignore.
Где используется
- Строки подключения к БД (
DATABASE_URL) - API-ключи и секреты (
JWT_SECRET,STRIPE_KEY,SMTP_PASSWORD) - Настройки порта и окружения (
PORT,NODE_ENV) - Feature-флаги (
FEATURE_NEW_UI=true)
Основной контент
Установка и использование
npm install dotenv
# .env (добавить в .gitignore!)
NODE_ENV=development
PORT=3000
DATABASE_URL=postgresql://user:password@localhost:5432/myapp
JWT_SECRET=super-secret-key-min-32-chars
REDIS_URL=redis://localhost:6379
SMTP_USER=noreply@example.com
SMTP_PASS=email-password
// app.js — ПЕРВОЙ строкой до всех импортов
require('dotenv').config;
// Теперь доступно через process.env
const port = process.env.PORT || 3000;
const dbUrl = process.env.DATABASE_URL;
const jwtSecret = process.env.JWT_SECRET;
console.log(`Server running in ${process.env.NODE_ENV} mode on port ${port}`);
Несколько .env файлов
.env # базовые значения (можно коммитить без секретов)
.env.development # overrides для dev
.env.production # overrides для production
.env.test # для тестов
.env.local # локальные overrides (не коммитить)
// Загрузить нужный файл
require('dotenv').config({ path: `.env.${process.env.NODE_ENV}` });
Конфигурационный модуль (рекомендуемый паттерн)
// config/index.js — единая точка конфигурации
require('dotenv').config;
function required(name) {
const value = process.env[name];
if (!value) throw new Error(`Missing required environment variable: ${name}`);
return value;
}
module.exports = {
env: process.env.NODE_ENV || 'development',
port: parseInt(process.env.PORT, 10) || 3000,
db: {
url: required('DATABASE_URL'),
maxConnections: parseInt(process.env.DB_MAX_CONNECTIONS, 10) || 10,
},
jwt: {
secret: required('JWT_SECRET'),
expiresIn: process.env.JWT_EXPIRES_IN || '7d',
},
redis: {
url: process.env.REDIS_URL || 'redis://localhost:6379',
},
isProduction: process.env.NODE_ENV === 'production',
isDevelopment: process.env.NODE_ENV === 'development',
};
// Использование в других файлах
const config = require('../config');
const pool = new Pool({ connectionString: config.db.url });
const token = jwt.sign(payload, config.jwt.secret, { expiresIn: config.jwt.expiresIn });
.env.example — документация переменных
# .env.example — этот файл КОММИТЯТ в git
# Скопируй в .env и заполни реальными значениями
NODE_ENV=development
PORT=3000
DATABASE_URL=postgresql://user:password@localhost:5432/myapp
JWT_SECRET= # минимум 32 символа, генерировать через: openssl rand -base64 32
REDIS_URL=redis://localhost:6379
# Новый разработчик:
cp .env.example .env
# Заполнить .env, затем запустить приложение
Частые ошибки
- Коммитить
.envв git — добавить.envв.gitignoreнемедленно после создания проекта - Не вызывать
dotenv.configпервым — если модуль сprocess.env.DB_URLимпортируется раньше dotenv, значение будетundefined - Не валидировать обязательные переменные — приложение запустится без
DATABASE_URLи упадёт в неочевидном месте; использовать функциюrequired - Хранить
.envв Docker образе — переменные передавать через-eфлаги или Docker secrets, не включать в образ