Optimasi Performa Development Environment Lokal

by Marcus Chen
Optimasi Performa Development Environment Lokal

Build 8 Menit, Kesabaran 0 Menit

Kamu lagi nunggu npm run build selesai. Sudah 4 menit. Kamu buka Twitter. 2 menit lagi. Kamu bikin kopi. Balik lagi — masih jalan. Total 8 menit buat satu build cycle.

Itu bukan masalah hardware. Laptop kamu punya 16GB RAM dan SSD. Masalahnya ada di konfigurasi development environment yang nggak pernah disentuh sejak pertama kali di-setup.

Artikel ini tentang optimasi performa development environment secara konkret — bukan teori, tapi perubahan config yang langsung terasa bedanya.


1. Docker: Volume Mount adalah Biang Keladi

Kalau kamu pakai Docker di macOS atau Windows, ini kemungkinan besar penyebab utama lambatnya environment kamu. Bind mount antara host dan container itu lambat secara fundamental di non-Linux karena ada layer filesystem translation.

Contoh docker-compose.yml yang bikin nangis:

services:
  app:
    image: node:20
    volumes:
      - .:/app  # ini masalahnya
    working_dir: /app
    command: npm run dev

Solusinya: pisahkan node_modules ke named volume, bukan bind mount.

services:
  app:
    image: node:20
    volumes:
      - .:/app
      - node_modules:/app/node_modules  # ini yang bikin cepat
    working_dir: /app
    command: npm run dev

volumes:
  node_modules:

Dengan cara ini, node_modules hidup sepenuhnya di dalam Docker filesystem, bukan di-sync bolak-balik ke host. Di pengalaman gue, ini bisa memangkas waktu cold start dari 45 detik jadi 8 detik.

Gotcha: Setelah ubah config ini, kamu perlu hapus volume lama dulu:

docker-compose down -v
docker-compose up --build

Kalau nggak, Docker masih pakai volume lama yang mungkin isinya campur aduk.


2. Webpack dan Vite: Cache yang Nggak Dimanfaatkan

Webpack 5 punya persistent cache yang by default... nggak aktif optimal. Banyak project yang setup-nya masih pakai pola lama.

Tambahkan ini ke webpack.config.js kamu:

module.exports = {
  cache: {
    type: 'filesystem',
    buildDependencies: {
      config: [__filename],
    },
    cacheDirectory: path.resolve(__dirname, '.webpack-cache'),
  },
  // ... config lainnya
};

Build pertama tetap sama. Build kedua dan seterusnya? Bisa 60–80% lebih cepat karena Webpack cuma rebuild module yang berubah.

Kalau kamu pakai Vite, kabar baiknya: Vite sudah pakai esbuild untuk pre-bundling dan cache-nya otomatis aktif di .vite/ folder. Tapi satu hal yang sering dilewatin — pastikan optimizeDeps di-configure dengan benar:

// vite.config.js
export default {
  optimizeDeps: {
    include: [
      'lodash-es',
      'axios',
      // tambahkan dependency besar yang sering kamu import
    ],
  },
};

Tanpa ini, Vite kadang re-bundle dependency di tengah development sesi, yang bikin browser reload tiba-tiba lambat.

Gotcha untuk Vite: Jangan commit folder .vite/ ke Git, tapi jangan juga taruh di .gitignore global. Taruh di .gitignore project-level supaya tiap developer punya cache sendiri.


3. Git: Repo Besar, Operasi Lambat

Kalau repo kamu sudah berumur 3+ tahun dan sering commit binary atau file besar, operasi Git seperti git status, git log, bahkan git checkout bisa mulai terasa berat.

Cek dulu ukuran repo kamu:

git count-objects -vH

Output yang perlu diperhatiin:

count: 1247
size: 2.34 MiB
in-pack: 89234
packs: 3
size-pack: 1.23 GiB  # kalau ini > 500MB, perlu action
prune-packable: 0
garbage: 0
size-garbage: 0 B

Langkah pertama, jalankan maintenance rutin:

git gc --aggressive --prune=now
git remote prune origin

Langkah kedua, aktifkan fitur core.fsmonitor supaya Git nggak perlu scan semua file setiap kali kamu jalankan command:

git config core.fsmonitor true
git config core.untrackedCache true

Di repo dengan 50.000+ file, ini bisa bikin git status dari 3 detik jadi di bawah 0.5 detik. Fitur ini pakai filesystem event dari OS (FSEvents di macOS, inotify di Linux) — bukan polling.

Gotcha: core.fsmonitor butuh Git 2.37+. Cek versi kamu dengan git --version. Kalau masih pakai Git lama (yang sering terjadi di Ubuntu 20.04 default), update dulu:

sudo add-apt-repository ppa:git-core/ppa
sudo apt update && sudo apt install git

4. Node.js: Memory Limit yang Terlalu Kecil

Ini error yang paling sering bikin bingung developer junior:

FATAL ERROR: CALL_AND_RETRY_LAST Allocation failed - JavaScript heap out of memory

By default, Node.js cuma dikasih sekitar 1.5GB heap memory. Untuk project besar dengan banyak dependency, ini bisa habis saat build.

Fix cepat — tambahkan ke script di package.json:

{
  "scripts": {
    "build": "node --max-old-space-size=4096 node_modules/.bin/webpack",
    "build:prod": "node --max-old-space-size=8192 node_modules/.bin/webpack --mode production"
  }
}

Atau kalau kamu mau set global untuk semua Node process di session terminal:

export NODE_OPTIONS="--max-old-space-size=4096"

Taruh baris ini di .bashrc atau .zshrc kamu supaya persistent.

Tapi jangan asal naikkan angkanya setinggi mungkin. Kalau kamu set 8192 di laptop 8GB RAM, kamu justru bikin sistem kamu thrashing karena swap. Rule of thumb: set ke 50–60% dari total RAM fisik kamu.


5. Terminal dan Shell: Startup Lambat Itu Nyata

Buka terminal baru, tunggu 2–3 detik sebelum prompt muncul. Itu bukan normal — itu tanda .zshrc atau .bashrc kamu kebanyakan plugin yang diload synchronously.

Diagnosis cepat:

# Untuk zsh
time zsh -i -c exit

# Untuk bash
time bash -i -c exit

Kalau hasilnya lebih dari 1 detik, ada yang perlu dibenahi.

Kalau kamu pakai Oh My Zsh, ini sering jadi pelakunya. Solusinya bukan hapus Oh My Zsh, tapi audit plugin yang kamu aktifkan:

# Di .zshrc, lihat baris ini:
plugins=(git docker kubectl terraform aws nvm rbenv pyenv)
# Plugin-plugin ini load tools yang mungkin nggak kamu pakai setiap hari

Ganti ke lazy loading untuk plugin berat. Contoh untuk nvm:

# Ganti ini:
export NVM_DIR="$HOME/.nvm"
[ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh"

# Dengan ini (lazy load):
export NVM_DIR="$HOME/.nvm"
nvm() {
  unset -f nvm node npm npx
  [ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh"
  nvm "$@"
}
node() { nvm; node "$@"; }
npm() { nvm; npm "$@"; }
npx() { nvm; npx "$@"; }

Dengan lazy loading, nvm baru di-load pertama kali kamu benar-benar manggil nvm, node, atau npm. Startup shell bisa turun dari 2.1 detik ke 0.3 detik.

Alternatif: Pertimbangkan ganti ke fnm (Fast Node Manager) yang ditulis di Rust. Instalasi dan switch versi Node-nya jauh lebih cepat dari nvm:

curl -fsSL https://fnm.vercel.app/install | bash

# Tambahkan ke .zshrc:
eval "$(fnm env --use-on-cd)"

6. Database Lokal: Index yang Terlupakan

Development database sering jalan tanpa index yang proper karena data-nya kecil — jadi lambatnya nggak kerasa. Tapi begitu kamu test dengan data yang lebih realistis, query tiba-tiba butuh 3 detik.

Habiskan 10 menit buat audit query development kamu. Di PostgreSQL:

-- Aktifkan logging slow query (di postgresql.conf atau session)
SET log_min_duration_statement = 100; -- log query > 100ms

-- Atau langsung analyze query spesifik
EXPLAIN (ANALYZE, BUFFERS, FORMAT TEXT)
SELECT u.*, p.title
FROM users u
JOIN posts p ON p.user_id = u.id
WHERE u.created_at > NOW() - INTERVAL '30 days'
ORDER BY p.created_at DESC
LIMIT 20;

Lihat output-nya. Kalau kamu lihat Seq Scan di tabel besar, itu tanda butuh index:

-- Tambahkan index yang missing
CREATE INDEX CONCURRENTLY idx_users_created_at ON users(created_at);
CREATE INDEX CONCURRENTLY idx_posts_user_id_created_at ON posts(user_id, created_at DESC);

Keyword CONCURRENTLY penting — ini bikin index dibuat tanpa lock tabel, jadi development kamu nggak terganggu selama proses indexing.

Gotcha: Index yang kamu buat di development database lokal nggak otomatis ada di staging atau production. Pastikan migration kamu include pembuatan index ini, dan gunakan CONCURRENTLY di migration juga supaya deployment ke production nggak bikin downtime.


Yang Gue Lakuin Sekarang

Dari semua poin di atas, urutan prioritas yang gue rekomendasikan:

  1. Docker volume fix — kalau kamu pakai Docker di macOS/Windows, ini ROI tertinggi. 30 menit setup, hasilnya langsung kerasa.
  2. Git fsmonitor — dua command, langsung aktif, nggak ada downside.
  3. Webpack/Vite cache — satu blok config, build kedua langsung lebih cepat.
  4. Shell lazy loading — butuh 15 menit audit .zshrc, tapi terminal kamu bakal terasa snappy.
  5. Node memory limit — fix ini kalau kamu sering ketemu heap error, atau kalau build kamu kadang crash tanpa jelas alasannya.
  6. Database index audit — jadwalkan ini sekali sebulan, terutama sebelum demo atau load testing.

Optimasi performa development environment bukan one-time task. Setiap kali kamu tambah dependency baru, tambah service baru, atau repo kamu makin besar — ada kemungkinan ada bottleneck baru yang muncul.

Mulai dari yang paling nyeri dulu. Kalau build kamu yang paling lambat, mulai dari sana. Kalau terminal yang paling bikin frustrasi, mulai dari shell. Jangan coba fix semuanya sekaligus — kamu nggak akan tahu mana yang actually berpengaruh.