Banyak tutorial Node.js langsung loncat ke npm install express tanpa peduli fondasi. Hasilnya? Tiga bulan kemudian kamu punya empat versi Node berbeda di satu mesin, node_modules yang tidak bisa direproduksi, dan rekan kerja yang tidak bisa menjalankan proyekmu karena "works on my machine".
Ini bukan soal pilih IDE terbaik atau tema terminal yang keren. Node.js development environment setup yang solid adalah soal konsistensi — antara mesinmu, server staging, dan mesin orang lain yang mungkin perlu clone repo-mu tahun depan.
Artikel ini adalah setup yang saya pakai sendiri. Opinionated, tapi ada alasannya.
Kenapa Version Manager Itu Wajib, Bukan Opsional
Jangan install Node langsung dari nodejs.org. Serius. Begitu kamu punya lebih dari satu proyek — dan kamu akan punya lebih dari satu proyek — kamu butuh bisa switch versi Node dengan cepat.
Ada dua pilihan utama: nvm dan fnm.
nvm sudah ada sejak lama, dokumentasinya lengkap, tapi lambat. Setiap buka terminal baru ada delay kecil yang lama-lama menyebalkan.
fnm (Fast Node Manager) ditulis dalam Rust. Kompatibel dengan file .nvmrc, tapi jauh lebih cepat. Ini yang saya pakai sekarang.
# Install fnm (macOS/Linux)
curl -fsSL https://fnm.vercel.app/install | bash
# Atau pakai Homebrew
brew install fnm
Tambahkan ini ke .zshrc atau .bashrc:
eval "$(fnm env --use-on-cd)"
Flag --use-on-cd penting — fnm akan otomatis switch versi Node saat kamu masuk ke direktori yang punya file .nvmrc atau .node-version.
Setelah itu:
# Install Node LTS terbaru (saat artikel ini ditulis: Node 20)
fnm install --lts
fnm use lts-latest
fnm default lts-latest
# Verifikasi
node --version # v20.x.x
npm --version # 10.x.x
Di root setiap proyek, selalu buat file .nvmrc:
20.11.0
Satu file kecil ini menyelamatkan banyak debugging sia-sia.
Package Manager: npm, yarn, atau pnpm?
Ini pertanyaan yang sering bikin perdebatan panjang. Pendapat saya singkat:
- npm — default, cukup untuk proyek solo atau kecil. Versi 9+ sudah jauh lebih baik dari reputasinya.
- yarn — saya tidak pakai lagi sejak yarn v1 mulai terasa stagnan dan yarn Berry (v2+) terlalu banyak konfigurasi untuk keuntungan yang tidak sepadan.
- pnpm — ini yang saya rekomendasikan untuk proyek serius.
pnpm menggunakan symlink dan content-addressable storage. Artinya satu package yang dipakai di sepuluh proyek hanya tersimpan sekali di disk. Instalasi lebih cepat, disk lebih hemat.
# Install pnpm via corepack (sudah bundled dengan Node 16+)
corepack enable
corepack prepare pnpm@latest --activate
# Verifikasi
pnpm --version # 9.x.x
Untuk memaksa tim (atau dirimu sendiri di masa depan) pakai package manager yang benar, tambahkan ini ke package.json:
{
"packageManager": "pnpm@9.1.0"
}
Field packageManager ini dibaca oleh corepack. Kalau seseorang coba jalankan npm install di proyek pnpm-mu, corepack akan warning.
Struktur Proyek yang Tidak Akan Bikin Menyesal
Ini struktur dasar yang saya mulai untuk hampir semua proyek Node.js backend:
my-project/
├── .nvmrc
├── .env.example # Commit ini, JANGAN .env
├── .gitignore
├── package.json
├── pnpm-lock.yaml # Selalu commit lockfile
├── tsconfig.json # Kalau pakai TypeScript
├── src/
│ ├── index.ts
│ ├── config/
│ ├── routes/
│ └── utils/
├── tests/
└── docker/
└── Dockerfile.dev
Beberapa hal yang sering diabaikan:
.env.example — Commit file ini dengan semua key tapi tanpa value. Jangan pernah commit .env asli. Tambahkan .env ke .gitignore dari hari pertama.
Lockfile — pnpm-lock.yaml, package-lock.json, atau yarn.lock harus di-commit. Ini yang memastikan pnpm install di CI menghasilkan dependency tree yang persis sama dengan di mesinmu.
tsconfig.json — Kalau pakai TypeScript (dan kamu sebaiknya pakai untuk proyek yang akan hidup lebih dari sebulan), ini konfigurasi minimal yang saya pakai:
{
"compilerOptions": {
"target": "ES2022",
"module": "NodeNext",
"moduleResolution": "NodeNext",
"outDir": "./dist",
"rootDir": "./src",
"strict": true,
"esModuleInterop": true,
"skipLibCheck": true
},
"include": ["src/**/*"],
"exclude": ["node_modules", "dist"]
}
"strict": true itu menyakitkan di awal tapi menyelamatkan nyawa di kemudian hari.
Tooling Harian: Formatter, Linter, dan Git Hooks
Ini bagian yang paling sering di-skip karena terasa seperti overhead. Padahal setup sekali, jalan selamanya.
Prettier + ESLint
pnpm add -D prettier eslint @eslint/js typescript-eslint
File .prettierrc:
{
"semi": false,
"singleQuote": true,
"tabWidth": 2,
"trailingComma": "es5",
"printWidth": 100
}
Konfigurasi ini opini saya — tidak ada semicolon, single quote. Kamu bisa beda, yang penting konsisten dan di-commit.
Untuk ESLint (v9+ pakai flat config):
// eslint.config.js
import js from '@eslint/js'
import tseslint from 'typescript-eslint'
export default tseslint.config(
js.configs.recommended,
...tseslint.configs.recommended
)
Husky + lint-staged untuk Git Hooks
Supaya linting jalan otomatis sebelum commit:
pnpm add -D husky lint-staged
pnpm exec husky init
Isi .husky/pre-commit:
pnpm exec lint-staged
Tambahkan ke package.json:
{
"lint-staged": {
"*.{ts,js}": ["eslint --fix", "prettier --write"],
"*.{json,md}": ["prettier --write"]
}
}
Sekarang setiap commit otomatis diformat. Tidak perlu debat soal style di code review.
Docker untuk Development: Overkill atau Wajib?
Untuk proyek yang butuh database, Redis, atau service lain — Docker Compose bukan overkill. Ini justru yang membuat Node.js development environment setup-mu reproducible di mesin siapapun.
Contoh docker-compose.dev.yml yang sering saya pakai:
services:
postgres:
image: postgres:16-alpine
environment:
POSTGRES_DB: myapp_dev
POSTGRES_USER: dev
POSTGRES_PASSWORD: devpassword
ports:
- "5432:5432"
volumes:
- postgres_data:/var/lib/postgresql/data
redis:
image: redis:7-alpine
ports:
- "6379:6379"
volumes:
postgres_data:
# Jalankan services
docker compose -f docker-compose.dev.yml up -d
# Cek status
docker compose -f docker-compose.dev.yml ps
Aplikasi Node-nya sendiri saya jalankan langsung di host (bukan di container) selama development. Ini biar hot-reload lebih cepat dan debugging lebih mudah. Hanya database dan external services yang di-containerize.
Kalau kamu mau tahu lebih dalam soal setup Docker untuk dev environment, ada artikel terpisah di /blog/docker-dev-environment-setup yang membahas ini lebih detail.
Scripts di package.json yang Wajib Ada
Ini scripts standar yang selalu ada di package.json saya:
{
"scripts": {
"dev": "tsx watch src/index.ts",
"build": "tsc --noEmit false",
"start": "node dist/index.js",
"lint": "eslint src/",
"lint:fix": "eslint src/ --fix",
"format": "prettier --write src/",
"typecheck": "tsc --noEmit",
"test": "node --experimental-vm-modules node_modules/.bin/jest"
}
}
Catatan: saya pakai tsx untuk development (bukan ts-node) karena jauh lebih cepat. Install dengan:
pnpm add -D tsx
tsx menggunakan esbuild di balik layar. Cold start yang biasanya 2-3 detik dengan ts-node jadi di bawah 500ms.
Perbandingan Pilihan Tooling
| Kategori | Opsi A | Opsi B | Yang Saya Pakai |
|---|---|---|---|
| Version Manager | nvm | fnm | fnm |
| Package Manager | npm | pnpm | pnpm |
| TS Runner (dev) | ts-node | tsx | tsx |
| Linter | ESLint | Biome | ESLint (ekosistem lebih matang) |
| Formatter | Prettier | Biome | Prettier |
| Test Runner | Jest | Vitest | Vitest (untuk proyek baru) |
Satu catatan soal Biome — ini tool baru (v1.0 rilis September 2023) yang menggabungkan linter dan formatter dalam satu binary Rust. Cepat. Tapi ekosistemnya belum selengkap ESLint + Prettier. Saya pakai ESLint + Prettier untuk proyek yang butuh plugin spesifik, Biome untuk proyek baru yang simpel.
Untuk test runner, Vitest jauh lebih enak untuk proyek TypeScript modern. Jest masih relevan kalau kamu stuck di ekosistem lama, tapi untuk proyek baru mulai 2024 saya default ke Vitest.
Satu Hal yang Sering Dilupakan: .gitignore yang Benar
# Dependencies
node_modules/
# Build output
dist/
build/
# Environment
.env
.env.local
.env.*.local
# Logs
*.log
npm-debug.log*
# OS
.DS_Store
Thumbs.db
# Editor
.vscode/
!.vscode/extensions.json
.idea/
Perhatikan: saya exclude .vscode/ tapi include .vscode/extensions.json. File extensions.json berguna untuk merekomendasikan ekstensi VS Code ke siapapun yang clone repo-mu, tanpa memaksakan settings personal.
Contoh .vscode/extensions.json:
{
"recommendations": [
"esbenp.prettier-vscode",
"dbaeumer.vscode-eslint",
"ms-vscode.vscode-typescript-next"
]
}
Kalau kamu juga sering kerja dengan self-hosted tools dan ingin setup yang lebih lengkap untuk workflow produktivitas, artikel tentang produktivitas engineer solo mungkin relevan.
Kesimpulan: Mulai Besok, Lakukan Ini
Node.js development environment setup yang solid bukan soal pakai tools paling baru atau paling populer. Soal konsistensi dan reproducibility.
Kalau kamu mau mulai dari nol besok, urutannya:
- Install
fnm, setup--use-on-cd - Install Node LTS via fnm, buat
.nvmrcdi setiap proyek - Enable corepack, pakai pnpm
- Setup Prettier + ESLint + Husky dari hari pertama
- Pakai
tsxuntuk dev, bukants-node - Docker Compose untuk external services
Satu langkah yang paling berdampak kalau kamu hanya mau melakukan satu hal: pasang fnm hari ini dan buat .nvmrc di semua proyek yang sedang aktif. Itu saja sudah menyelesaikan 80% masalah "works on my machine".
Kalau ada setup spesifik yang ingin kamu tanyakan atau ada yang berbeda dari cara kamu kerja — tinggalkan komentar. Saya penasaran apa yang orang lain pakai di 2024.