# Kenapa Ada Tanda ^ dan ~ di package.json, dan Kapan Harus Dipakai?

Oleh Roma, Series "Fundamental JavaScript & Praktik Terbaik Pengembangan Modern"


Pernah nggak, abis npm install, tiba-tiba ada fitur yang biasanya jalan malah error? Kemungkinan besar penyebabnya bukan kodemu, tapi dua simbol kecil di package.json yang sering diabaikan: ^ dan ~.

Kelihatannya sepele, cuma karakter di depan nomor versi. Tapi dua simbol ini yang nentuin seberapa jauh npm install boleh "jalan sendiri" naikin versi dependency kamu tanpa nanya dulu.

# Apa Itu Dependency, Sih?

Dependency adalah pustaka atau paket eksternal yang dibutuhkan proyekmu buat jalan. Kalau kamu pakai React, ya React itu sendiri sudah termasuk dependency.

Contoh di package.json:

"dependencies": {
  "react": "^18.2.0",
  "axios": "~1.3.2"
}

React dikontrol pakai ^, Axios pakai ~. Bedanya baru kelihatan pas kamu jalanin npm install atau npm update.

# Simbol ^ (Caret): Fleksibel Tapi Nggak Sampai Lompat Major

^ ini yang paling sering muncul di package.json bawaan npm init. Dia ngizinin update minor dan patch, tapi versi major tetap dikunci, soalnya versi major biasanya bawa breaking changes.

"lodash": "^4.17.21"

Rentang yang diterima: mulai dari 4.17.21 sampai sebelum 5.0.0. Jadi npm install bisa naikin ke 4.18.0 atau 4.20.2, tapi nggak akan pernah lompat ke 5.0.0.

Enaknya, kamu tetap kebagian perbaikan bug dan fitur kecil tanpa perlu update manual tiap saat. Risikonya, versi minor yang baru itu kadang juga bawa bug baru yang belum ketauan, jadi tetap perlu dites setelah update.

# Simbol ~ (Tilde): Lebih Galak Soal Kestabilan

~ cuma ngizinin update di angka patch, level ketiga di semver. Cocok kalau kamu emang butuh kestabilan penuh dan males kena kejutan.

"express": "~4.18.1"

Yang diterima cuma 4.18.1 sampai sebelum 4.19.0. Jadi npm install bisa naikin ke 4.18.2 atau 4.18.9, tapi 4.19.0 ditolak karena itu udah naik minor.

Ini jauh lebih aman dari sisi behavior library yang berubah tiba-tiba, tapi konsekuensinya kamu bisa ketinggalan fitur baru yang sebenarnya berguna, sampai kamu update manual.

# Aturan Mainnya: Semantic Versioning

Biar ^ dan ~ masuk akal, perlu ngerti dulu pola semver: MAJOR.MINOR.PATCH.

Ambil contoh 2.5.3. Major (2) berarti perubahan besar yang berpotensi breaking changes. Minor (5) berarti fitur baru yang tetap backward-compatible. Patch (3) berarti perbaikan bug tanpa fitur baru.

^ mengunci di angka major. ~ mengunci sampai ke angka minor. Itu aja bedanya, tapi dampaknya lumayan besar buat proyek yang jalan lama.

# Kapan Pakai yang Mana?

Ini bukan soal mana yang "lebih benar", tapi soal toleransi risiko proyekmu.

Saya pribadi pakai ^ buat dependency yang aktif dikembangkan dan reputasinya bagus soal backward-compatibility, semacam React atau library UI populer lainnya. Buat yang sifatnya kritis, kayak database driver atau library autentikasi, saya lebih pilih ~, karena kalau ada bug yang nyelip dari update minor, dampaknya bisa langsung ke produksi.

Kalau proyekmu masih tahap development aktif dan kamu nggak keberatan ngetes ulang tiap ada update, ^ masuk akal. Kalau proyeknya udah live dan kamu nggak mau ada kejutan, ~ lebih masuk akal, meskipun konsekuensinya kamu harus lebih rajin ngecek changelog manual.

# Studi Kasus Kecil: Proyek E-commerce

Misalnya kamu lagi pegang proyek e-commerce yang pakai React, Redux, dan Axios.

React biasanya aman dipasang ^18.2.0, soalnya tim React historisnya jarang bikin perubahan besar yang menyelinap lewat versi minor. Tapi Axios yang dipakai buat komunikasi API pembayaran, saya lebih nyaman kunci pakai ~1.3.2. Kalau ada bug kecil dari fitur baru yang belum ketauan, saya nggak mau itu nyangkut di jalur transaksi.

Nggak ada aturan tunggal yang berlaku ke semua dependency di satu proyek. Yang penting kamu sadar mana yang boleh "santai" dan mana yang harus dikunci ketat.

# Ngecek dan Ngontrol Dependency dari Terminal

Beberapa perintah yang biasa saya pakai buat mantau ini:

npm outdated

Ngecek dependency mana yang punya versi lebih baru dari yang terpasang.

npm update

Update sesuai rentang yang udah diizinin ^ atau ~ di package.json.

npm install <package>@latest

Update paksa ke versi terbaru, walau itu keluar dari rentang ^ atau ~ yang udah diatur.

Kalau butuh kunci total tanpa toleransi sama sekali, hapus simbolnya:

"axios": "1.3.2"

Konsekuensinya, npm install nggak akan naikin versi itu sama sekali sampai kamu ubah manual. Cocok buat dependency yang benar-benar sensitif, tapi jangan dipakai di semua baris, nanti kamu yang capek update satu-satu.

# Kalau Udah Masuk CI/CD

Di pipeline yang lebih matang, biasanya ada tools yang bantu ngatur update ini otomatis. Renovate bisa bikin PR update berdasarkan rentang ^/~ yang udah kamu tentuin. Dependabot di GitHub kerjanya mirip, mindai dependency dan ngusulin update sesuai konfigurasi.

Keduanya nggak menggantikan keputusan kamu soal ^ vs ~, cuma bikin proses update-nya nggak perlu dicek manual satu-satu tiap minggu.

# Penutup

Simbol ^ dan ~ itu bukan detail yang bisa diabaikan begitu aja. Sekali proyekmu kena bug gara-gara update otomatis yang nggak kamu duga, biasanya baru kepikiran buat balik cek package.json baik-baik.

Coba buka package.json proyekmu sekarang, cek dependency yang paling kritis, terus tanya ke diri sendiri: kalau versinya naik otomatis besok pagi, kamu siap atau enggak? Kalau jawabannya enggak, itu kandidat kuat buat dikunci pakai ~, atau bahkan tanpa simbol sama sekali.