Node.js membawa JavaScript keluar dari browser menjadi runtime di server dan alat command line, dan kini menjadi tulang punggung banyak tooling development modern — dari bundler web sampai framework backend. Pengelola package bawaannya, npm, adalah salah satu yang terbesar di dunia. Namun Node.js bergerak cepat: versi besar baru muncul tiap beberapa bulan, dan proyek berbeda sering butuh versi berbeda pula. Pada Chapter ini kita meninjau instalasi Node.js di Linux, membaca package.json sebagai pusat proyek, membedah folder node_modules, lalu mengatur multi-versi dengan nvm.

Meninjau Instalasi Node.js #

Debian mengemas Node.js sebagai package nodejs dengan dua program utama: node sebagai runtime dan npm sebagai pengelola package. Mari periksa keadaan pada mesin uji:

bash
which node npm
node --version
npm --version
corepack --version
node -e "const harga = [1500, 2500, 4000]; console.log(harga.map(x => x * 2));"

Output yang Dihasilkan:

text
/usr/bin/node
/usr/bin/npm
v24.21.0
11.19.0
0.36.0
[ 3000, 5000, 8000 ]

Bedah hasilnya:

  1. which node npm: kedua program berada di /usr/bin — dipasang lewat package nodejs dan npm dari repository distro.
  2. node --version dan npm --version: mesin uji menjalankan Node v24.21.0 dan npm 11.19.0 — angka cepat berubah mengikuti rilis, jadi angka di komputer Anda hampir pasti berbeda, dan itu normal.
  3. corepack --version: corepack adalah agen kecil yang ikut terpasang untuk mengelola manajer package alternatif (yarn, pnpm) — kita bahas singkat di bagian akhir.
  4. node -e "...": menjalankan potongan JavaScript langsung dari argumen. Perhatikan bahwa console.log memformat array dengan rapi — bahasa yang sama yang dulu hanya hidup di console browser.

Interpreter node membaca JavaScript langsung tanpa tahap kompilasi terpisah — mirip Python pada Chapter sebelumnya, bedanya ekosistem Node membawa pengelola dependensi ke dalam runtime-nya sendiri.

package.json sebagai Pusat Proyek #

Setiap proyek Node diawali satu file: package.json. File ini mencatat nama, versi, entry point, script perintah, dan daftar dependensi — semacam kartu identitas sekaligus resep pembangunan proyek. Perintah npm init membuatnya, dan opsi -y menerima semua nilai bawaan tanpa kuesioner:

bash
mkdir -p aplikasi-catatan
cd aplikasi-catatan
npm init -y
jq -r ".name, .main" package.json

Output yang Dihasilkan:

text
Wrote to /home/budi/aplikasi-catatan/package.json:

{
  "name": "aplikasi-catatan",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "type": "commonjs"
}


aplikasi-catatan
index.js

Bedah hasil dan isi package.json:

  1. npm init -y: menulis package.json di folder kerja dengan nilai bawaan; npm melaporkan lokasi penulisannya, lalu menggiring isi lengkapnya ke stdout.
  2. Isi JSON-nya: name dan version mengidentifikasi proyek; main menunjuk file yang dimuat ketika proyek di-require sebagai module; scripts mendefinisikan perintah-perintah yang bisa dijalankan ulang; type menentukan format module — commonjs memakai require(), sedangkan module memakai import.
  3. jq -r ".name, .main" package.json: membaca dua field itu kembali — kebiasaan memeriksa file hasil otomasi dengan jq seperti pada Chapter jq dan JSON Processing membuat kita percaya tapi memverifikasi.

node_modules dan Instalasi Package #

Perintah npm install nama-package mengunduh package beserta seluruh pohon dependensinya ke folder node_modules/ di dalam proyek, mencatatnya di field dependencies pada package.json, dan mengunci versi pastinya di package-lock.json. Untuk melihat mekanismenya tanpa unduhan jaringan, kita pakai package lokal: folder paket-sapa di sebelah proyek, dipasang dengan alamat foldernya — secara mekanis hasilnya sama dengan instalasi dari registry npm:

bash
mkdir -p paket-sapa
cat > paket-sapa/package.json << 'AKHIR'
{
  "name": "paket-sapa",
  "version": "1.0.0",
  "description": "Paket contoh untuk latihan",
  "main": "index.js",
  "bin": { "sapa": "./cli.js" }
}
AKHIR
cat > paket-sapa/index.js << 'AKHIR'
module.exports = function sapa(nama) {
  return "Halo, " + nama + "!";
};
AKHIR
cat > paket-sapa/cli.js << 'AKHIR'
#!/usr/bin/env node
const sapa = require("./index.js");
console.log(sapa(process.argv[2] || "dunia"));
AKHIR
mkdir -p aplikasi-catatan
cd aplikasi-catatan
npm init -y > /dev/null
npm install --silent ../paket-sapa
ls -1 node_modules
ls -1 node_modules/.bin
printf 'const sapa = require("paket-sapa");\nconsole.log(sapa("Budi"));\n' > index.js
node index.js
npx sapa Siti

Output yang Dihasilkan:

text
paket-sapa
sapa
Halo, Budi!
Halo, Siti!

Bedah perjalanan package tersebut:

  1. Fixture paket-sapa: field main menandai file yang dimuat saat require(); field bin memetakan nama perintah sapa ke file cli.js — persis cara package seperti eslint atau prettier menyediakan perintah mereka.
  2. npm install --silent ../paket-sapa: menyalin package ke node_modules/. Opsi --silent meredam ringkasan progres yang memuat angka waktu — pada instalasi dari registry npm sungguhan, outputnya berupa added N packages plus daftar peringatan bila ada.
  3. ls -1 node_modules dan ls -1 node_modules/.bin: package mendarat di folder namanya, dan npm sekaligus membuat symlink sapa di .bin.
  4. node index.js: require("paket-sapa") dicari oleh Node berjalan naik dari folder kerja sampai menemukan node_modules/paket-sapa — karena itu kita tidak perlu menyebut lokasi foldernya.
  5. npx sapa Siti: menjalankan perintah dari node_modules/.bin tanpa perlu mengetik pathnya; bila perintah tidak ditemukan lokal, npx menawarkan untuk mengunduhnya sekali pakai dari registry.

Folder node_modules bisa memuat ribuan folder karena setiap dependensi membawa dependensinya sendiri. Ukurannya bisa ratusan megabyte per proyek — makanya folder ini tidak pernah dimasukkan ke version control dan selalu dibangun ulang dari package.json.

npm run dan Scripts #

Field scripts di package.json adalah tempat mendefinisikan perintah proyek — uji, build, menjalankan server — supaya seluruh tim mengetik hal yang sama. Perintah npm pkg set mengedit field itu dari terminal:

bash
mkdir -p aplikasi-catatan
cd aplikasi-catatan
npm init -y > /dev/null
printf 'console.log("server catatan berjalan");\n' > index.js
npm pkg set scripts.mulai="node index.js"
jq ".scripts" package.json
npm run mulai

Output yang Dihasilkan:

text
{
  "test": "echo \"Error: no test specified\" && exit 1",
  "mulai": "node index.js"
}

> [email protected] mulai
> node index.js

server catatan berjalan

Bedah hasilnya:

  1. npm pkg set scripts.mulai="node index.js": menambahkan entri mulai ke field scripts — jq mengonfirmasi hasilnya tertulis rapi di package.json.
  2. npm run mulai: mengeksekusi script tersebut. Baris > [email protected] mulai adalah header npm, dan perintah beserta keluarannya mengikuti di bawahnya.
  3. Nama khusus: beberapa nama script punya pintasan — npm start untuk start, npm test untuk test, npm run build untuk yang lainnya. Konvensi ini membuat CI/CD dan rekan tim tahu harus memanggil apa tanpa membaca README.

nvm untuk Multi Versi #

Kebutuhan multi-versi di Node dijawab oleh nvm (Node Version Manager) — pasangannya pyenv di dunia Python. nvm dipasang per-user lewat script instalasi dari repositori resminya, lalu dimuat sebagai fungsi shell; semua versi Node tinggal di bawah ~/.nvm/versions dan pergantian versi dilakukan dengan memanipulasi PATH — mekanisme yang sama dengan yang kita bahas di Chapter Compilers dan Build Tools . Sebagai contoh tampilan, pemasangan versi LTS lewat nvm umumnya tampak seperti ini:

text
Downloading and installing node v22.20.0...
(100%)%
Now using node v22.20.0 (npm v10.9.0)

Perintah nvm install 22 memasang satu versi, nvm use 22 mengganti versi aktif untuk shell saat ini, dan file .nvmrc berisi nomor versi di root proyek supaya nvm use tanpa argumen membacanya. Karena nvm hidup di home directory, tidak ada satu file sistem pun yang tersentuh — berbeda dengan apt yang hanya menyediakan satu versi Node untuk seluruh sistem.

Global, Lokal, dan corepack #

Instalasi package pada dasarnya lokal — masuk node_modules proyek. Opsi npm install -g memasang secara global ke folder sistem (/usr/lib/node_modules) sehingga perintahnya tersedia di mana saja, tetapi di Debian lokasi itu milik root: praktik yang lebih aman adalah membiarkan npm global diatur per-user oleh nvm, atau cukup pakai npx untuk perintah sesekali. Adapun corepack mengisi ceruk lain: manajer package alternatif yarn dan pnpm bisa diaktifkan satu per satu dengan corepack enable, lalu corepack yang menjalankan versi persis yang tertulis di field packageManager pada package.json — menjamin seluruh tim memakai manajer package berversi sama. Rincian perintahnya ada di node(1) , npm(1) , dan npx(1) .

Ekosistem Node menempuh banyak mekanisme demi kenyamanan dependensi per proyek. Chapter berikutnya menoleh ke bahasa yang justru memilih kesederhanaan: Go — satu binary statis, satu perintah go untuk semuanya.