Aplikasi etalase Budi berjalan sempurna di laptopnya, lalu berhenti di server: alamat API tertulis langsung di kode menunjuk ke localhost, dan kunci API produksi yang ia tempelkan di kode ikut terbaca oleh semua orang yang membuka repository. Dua masalah, satu akar: nilai yang seharusnya berbeda antar lingkungan ditulis mati di dalam kode.

Environment configuration memisahkan nilai-nilai itu dari kode. Nilai yang berubah-ubah — alamat API, port, mode aplikasi, kunci — diserahkan ke environment variable yang diatur di tempat aplikasi berjalan. Kode yang sama mengalir ke laptop pengembang, server produksi, dan mesin CI, sementara tiap tempat memberi nilainya sendiri. Chapter ini mempraktikkan pembacaannya lewat process.env, membahas konvensi NODE_ENV, lalu menjelaskan mekanisme berkas .env — semuanya tanpa pemasangan package tambahan.

process.env: Jembatan ke Lingkungan #

Di Node.js, seluruh environment variable yang aktif saat proses dimulai tersedia sebagai object process.env. Kuncinya berupa nama variabel (misalnya NODE_ENV), nilainya selalu string — atau undefined bila tidak diatur. Berkas berikut membaca tiga variabel dengan nilai cadangan:

js env-demo.js
// env-demo.js — membaca konfigurasi dari environment
const mode = process.env.NODE_ENV ?? "development";
const appMode = process.env.APP_MODE ?? "web";
const port = process.env.PORT ?? "3000";

console.log(`mode      : ${mode}`);
console.log(`app mode  : ${appMode}`);
console.log(`port      : ${port}`);
console.log(`PATH ada  : ${"PATH" in process.env}`);

Menjalankannya tanpa mengatur apa pun memberikan semua nilai cadangan:

bash
node env-demo.js

Output yang Dihasilkan:

text
mode      : development
app mode  : web
port      : 3000
PATH ada  : true

Kini variabelnya diatur saat memanggil perintah — sintaks NAMA=nilai di depan perintah berlaku untuk shell Linux, macOS, dan lingkungan CI:

bash
NODE_ENV=production APP_MODE=api PORT=8080 node env-demo.js

Output yang Dihasilkan:

text
mode      : production
app mode  : api
port      : 8080
PATH ada  : true

Mari kita bedah pola pada berkasnya:

  1. Baris 2 (process.env.NODE_ENV ?? "development"): operator ?? memberi nilai cadangan hanya bila variabel undefined atau null — persis situasi variabel yang belum diatur. Dengan pola ini, kode tetap bisa dijalankan bahkan tanpa satu pun environment variable.
  2. Baris 4 (process.env.PORT ?? "3000"): nilai cadangan ditulis sebagai string "3000", bukan angka 3000. Seluruh isi process.env bertipe string; membandingkannya dengan angka akan membingungkan.
  3. Baris 8 ("PATH" in process.env): operator in memeriksa keberadaan kunci. PATH selalu ada di lingkungan shell kita (berisi daftar folder tempat perintah dicari), dan hasilnya true di kedua percobaan — bukti bahwa process.env berisi lingkungan nyata, bukan object kosong.

NODE_ENV dan Konvensi Penamaan #

Dari semua nama variabel, NODE_ENV berkedudukan khusus: ekosistem Node menyepakatinya sebagai penanda lingkungan, dengan tiga nilai yang lazim — development saat menulis kode, test saat menjalankan test, dan production saat aplikasi melayani pengguna. Banyak alat mengubah perilakunya berdasarkan nilai ini: framework web mencetak pesan kesalahan yang lebih rinci di development, dan beberapa library menonaktifkan pemeriksaan yang mahal di production.

Variabel lain mengikuti konvensi nama huruf besar dengan pemisah garis bawah — APP_MODE, PORT, API_URL — sehingga mudah dibedakan dari identifier biasa. Nilai APP_MODE pada contoh kita (misalnya web atau api) adalah contoh variabel tambahan milik aplikasi sendiri: penamaannya bebas, karena yang disepakati ekosistem hanya NODE_ENV.

Berkas .env: Format dan Pemuatannya #

Praktik umum untuk menyimpan nilai-nilai itu adalah berkas .env di folder proyek. Formatnya sederhana — satu pasangan NAMA=nilai per baris, tanpa export, tanpa tanda kutip yang wajib:

text contoh isi berkas .env
APP_MODE=api
PORT=8080

Node tidak membaca berkas ini secara otomatis; seseorang harus memuatnya ke process.env sebelum kode berjalan. Dua jalur yang umum:

  • Library dotenv: package paling populer untuk pekerjaan ini. Kita memasangnya sendiri (npm install dotenv) lalu memanggilnya paling atas di titik masuk aplikasi; library tersebut membaca .env dan mengisikan process.env. Karena chapter ini sengaja tanpa pemasangan tambahan, kita tidak menggunakannya di sini — polanya cukup dipahami: pemuatan terjadi sebelum kode aplikasi membaca process.env.
  • Bawaan Node --env-file: sejak Node 20, flag --env-file membaca berkas .env saat proses dimulai, tanpa package apa pun. Node 24 yang kita pakai mendukungnya penuh, dan berikut bukti nyatanya:
bash
node --env-file=konfig.env baca-env.js

Output yang Dihasilkan:

text
APP_MODE = api
PORT     = 8080

Berkas konfig.env berisi dua baris yang sama dengan contoh .env di atas, dan baca-env.js hanya mencetak kedua nilai:

js baca-env.js
console.log(`APP_MODE = ${process.env.APP_MODE}`);
console.log(`PORT     = ${process.env.PORT}`);

Sebagai pembanding, menjalankan node baca-env.js tanpa flag menghasilkan APP_MODE = undefined dan PORT = undefined — nilai itu memang hanya datang dari pemuat.

Dengan konfigurasi yang rapi, kode yang sama berjalan di semua lingkungan — tetapi begitu kode dikirim ke pengguna, biasanya ia bukan lagi kode asli, melainkan hasil build. Cara membaca kembali kode hasil build itulah topik chapter berikutnya.

Berkas Sumber

Berkas pendukung halaman ini dapat diunduh dan dijalankan langsung sesuai penjelasan di atas.

baca-env.js

Unduh berkas
javascript
console.log(`APP_MODE = ${process.env.APP_MODE}`);
console.log(`PORT     = ${process.env.PORT}`);

env-demo.js

Unduh berkas
javascript
// env-demo.js — membaca konfigurasi dari environment
const mode = process.env.NODE_ENV ?? "development";
const appMode = process.env.APP_MODE ?? "web";
const port = process.env.PORT ?? "3000";

console.log(`mode      : ${mode}`);
console.log(`app mode  : ${appMode}`);
console.log(`port      : ${port}`);
console.log(`PATH ada  : ${"PATH" in process.env}`);