Environment Variables — dotenv, process.env, konfiguratsiya

~15 daq · Node.js · Amaliy

Muammodan boshlaylik

Yangi dasturchining kodida ko'pincha shunday qatorlar ko'rinadi:

const db = mongoose.connect('mongodb://admin:parol123@localhost:27017/myapp');
const jwtSecret = 'mening-maxfiy-kalitim';
const apiKey = 'sk-live-abc123xyz789';

Kod GitHub ga push qilindi. Ertasi kuni ma'lumotlar bazasi buzib kirildi, API hisob o'chirildi, JWT tokenlar soxtalashtirildi.

Bu — hardcoded credentials muammosi. Maxfiy ma'lumotlar hech qachon kodda yozilmaydi. Environment variables aynan shu uchun.


Environment variable nima?

Environment variable — operatsion tizim darajasida saqlanadigan kalit-qiymat juftligi. Dastur ishga tushganda ularni o'qiydi. Kod ichida yozilmaydi — har bir muhitda (local, staging, production) alohida belgilanadi.

Hayotiy o'xshatma: restoran oshpazi retseptni biladi, lekin maxsus ziravorlarni ombor xonasida saqlaydi — retseptda "ombordan ol" deb yozilgan, ziravorning o'zi retseptda ko'rsatilmaydi. Environment variable ham shunday: kod "muhitdan ol" deydi, qiymat esa tashqarida.


process.env — o'rnatilgan mexanizm

Node.js da environment variable lar process.env orqali o'qiladi:

console.log(process.env.HOME);     // /home/jasur
console.log(process.env.PATH);     // /usr/local/bin:/usr/bin:...
console.log(process.env.NODE_ENV); // "development" yoki "production"

O'zingizning o'zgaruvchilaringizni terminal orqali berish:

# Linux/Mac
DB_URL=mongodb://localhost:27017 PORT=4000 node server.js

# Windows PowerShell
$env:DB_URL="mongodb://localhost:27017"; $env:PORT="4000"; node server.js
// server.js
const port  = process.env.PORT  || 3000;
const dbUrl = process.env.DB_URL;

console.log(`Port: ${port}`);
console.log(`DB: ${dbUrl}`);

|| 3000 — muhitda PORT berilmagan bo'lsa, standart qiymat ishlaydi.


dotenv — .env fayl

Har safar terminaldi o'zgaruvchilar yozish noqulay. dotenv kutubxonasi .env faylidagi o'zgaruvchilarni avtomatik process.env ga yuklaydi.

npm install dotenv
# .env fayl — loyiha ildizida
PORT=3000
NODE_ENV=development

DB_HOST=localhost
DB_PORT=5432
DB_NAME=myapp
DB_USER=postgres
DB_PASS=secret123

JWT_SECRET=juda-uzun-va-tasodifiy-satr-kamida-32-belgi
JWT_EXPIRES_IN=7d

REDIS_URL=redis://localhost:6379

SMTP_HOST=smtp.gmail.com
SMTP_PORT=587
SMTP_USER=noreply@myapp.uz
SMTP_PASS=app-password-here
// server.js — eng birinchi qatorda yuklash
require('dotenv').config();

// Endi process.env da mavjud
const port      = process.env.PORT || 3000;
const dbHost    = process.env.DB_HOST;
const jwtSecret = process.env.JWT_SECRET;

Nima uchun eng boshida? dotenv.config() chaqirilgunga qadar process.env da ular yo'q. Boshqa modullar import qilinishidan oldin yuklash kerak.


.gitignore — asosiy qoida

.env fayli hech qachon git ga qo'shilmaydi:

# .gitignore
.env
.env.local
.env.production

O'rniga .env.example fayli yaratiladi — qiymatlar bo'sh, faqat qaysi o'zgaruvchilar kerakligi ko'rsatiladi:

# .env.example — git ga qo'shiladi, komandaga ko'rsatish uchun
PORT=
NODE_ENV=

DB_HOST=
DB_PORT=
DB_NAME=
DB_USER=
DB_PASS=

JWT_SECRET=
JWT_EXPIRES_IN=

REDIS_URL=

SMTP_HOST=
SMTP_PORT=
SMTP_USER=
SMTP_PASS=

Yangi dasturchi loyihaga qo'shilganda: .env.example ni ko'chirib .env yaratadi, qiymatlarni to'ldiradi.


Konfiguratsiya moduli — yaxshi pattern

process.env ni hamma joydan to'g'ridan-to'g'ri o'qish yomon amaliyot — qiymat yo'q bo'lsa dastur o'rta joyda xato beradi. Yaxshisi barcha konfiguratsiyani bir joyda yig'ib, tekshirib, export qilish:

// src/config/index.js
require('dotenv').config();

function talab(nomi) {
  const qiymat = process.env[nomi];
  if (!qiymat) {
    throw new Error(`Muhit o'zgaruvchisi topilmadi: ${nomi}`);
  }
  return qiymat;
}

function ixtiyoriy(nomi, standart) {
  return process.env[nomi] || standart;
}

module.exports = {
  port: ixtiyoriy('PORT', '3000'),
  nodeEnv: ixtiyoriy('NODE_ENV', 'development'),

  db: {
    host: talab('DB_HOST'),
    port: ixtiyoriy('DB_PORT', '5432'),
    name: talab('DB_NAME'),
    user: talab('DB_USER'),
    pass: talab('DB_PASS'),
  },

  jwt: {
    secret:    talab('JWT_SECRET'),
    expiresIn: ixtiyoriy('JWT_EXPIRES_IN', '7d'),
  },

  smtp: {
    host: talab('SMTP_HOST'),
    port: ixtiyoriy('SMTP_PORT', '587'),
    user: talab('SMTP_USER'),
    pass: talab('SMTP_PASS'),
  },

  isProd: process.env.NODE_ENV === 'production',
  isDev:  process.env.NODE_ENV === 'development',
};
// server.js
const config = require('./src/config');

app.listen(config.port, () => {
  console.log(`Server: http://localhost:${config.port}`);
  console.log(`Muhit: ${config.nodeEnv}`);
});

// db.js
const config = require('./src/config');
const pool = new Pool({
  host:     config.db.host,
  port:     config.db.port,
  database: config.db.name,
  user:     config.db.user,
  password: config.db.pass,
});

Nima uchun bu yaxshi? Server ishga tushishi bilan barcha talab qilingan o'zgaruvchilar tekshiriladi. Biror biri yo'q bo'lsa — darhol aniq xato xabari, emas biror joyda undefined muammosi.


NODE_ENV — muhitni belgilash

NODE_ENV — qaysi muhitda ishlayotganini bildiradi. Dasturning xulqi shunga qarab o'zgaradi:

const config = require('./config');

// Xatolar faqat devda batafsil
app.use((err, req, res, next) => {
  if (config.isDev) {
    res.json({ error: err.message, stack: err.stack });
  } else {
    res.json({ error: 'Ichki xato' }); // produksiyada stack ko'rsatilmaydi
  }
});

// Log darajasi
const logDarajasi = config.isProd ? 'error' : 'debug';

NODE_ENV uchta standart qiymat oladi: development, production, test.


Produksiyada environment variables

Produksiyada .env fayli serverga ko'chirilmaydi — o'zgaruvchilar platformada to'g'ridan-to'g'ri belgilanadi:

VPS (Linux):

# /etc/environment yoki systemd service faylida
Environment="PORT=3000"
Environment="DB_PASS=super-secret"

Vercel, Render, Railway: Dashboard → Settings → Environment Variables → Kalit va qiymat qo'shiladi.

Docker:

docker run -e PORT=3000 -e DB_PASS=secret myapp
# docker-compose.yml
services:
  app:
    image: myapp
    environment:
      - PORT=3000
      - DB_PASS=secret
    # yoki fayldan
    env_file:
      - .env.production

Tez-tez uchraydigan xatolar

Qayta ishga tushirmay kutish

// .env ga qiymat qo'shdingiz — lekin server hali eski holat bilan ishlayapti
// ✅ Serverni qayta ishga tushiring

Raqam sifatida o'qish

// process.env dan kelgan barcha qiymatlar — STRING
const port = process.env.PORT;
typeof port; // "string", "number" emas!

// ✅ Raqamga aylantirish kerak bo'lsa
const port = Number(process.env.PORT) || 3000;
// yoki
const port = parseInt(process.env.PORT, 10) || 3000;

Boolean qiymat

// ❌ Bu har doim true — "false" ham truthy string
const debugMode = process.env.DEBUG_MODE;
if (debugMode) { ... }

// ✅ String bilan taqqoslash
const debugMode = process.env.DEBUG_MODE === 'true';

.env faylini git ga push qilish

# Git ga qo'shib yuborgan bo'lsangiz — tarixdan ham o'chirish kerak
git rm --cached .env
git commit -m "env faylini tarixdan o'chirish"
# Va barcha maxfiy kalitlarni almashtirishni unutmang!

Xulosa

Environment variables — maxfiy ma'lumotlarni koddan ajratishning standart usuli. Bu professional dasturlashning asosiy qoidalaridan biri.

Eslab qoling:

  • Maxfiy ma'lumotlar hech qachon kodda yozilmaydi
  • dotenv — .env faylini process.env ga yuklaydi
  • .env — .gitignore da, .env.example — gitda
  • process.env dan kelgan barcha qiymatlar string
  • Konfiguratsiya modulida talab qilingan o'zgaruvchilar tekshiriladi
  • NODE_ENV — development, production, test
  • Produksiyada hosting platformasi dashboard da belgilanadi

Node.js kursi tugallandi. Tabriklaymiz!

Siz Node.js ning asosi — Event Loop, Core modullar, Stream, Process, va amaliy vositalarni o'rgandingiz. Endi Express yoki NestJS bilan real API yaratishga tayyorsiz.