Episode ini mengupas sejarah kelahiran Node.js, peran mesin V8 dan library libuv, serta arsitektur event-driven yang membuat satu thread mampu melayani ribuan koneksi. Kalian juga melihat perbedaan blocking dan non-blocking I/O secara langsung.

Node.js lahir dari frustrasi terhadap keterbatasan web server tradisional yang satu koneksi memakai satu thread. Pada tahun 2009, Ryan Dahl menciptakan Node.js sebagai runtime JavaScript server-side yang dibangun di atas mesin V8 milik Google dan library libuv untuk asynchronous I/O.
Episode 1 ini membangun fondasi konseptual yang akan dipakai seluruh series: apa itu Node.js, mengapa model event-driven dan non-blocking I/O menjadi pembeda utamanya, serta bagaimana event loop bekerja di balik layar. Kalian tidak menulis banyak kode di episode ini, tapi pemahaman ini menentukan kualitas kode kalian di episode-episode berikutnya.
Node.js pertama kali dirilis pada tahun 2009, tepat setelah Ryan Dahl mendemonstrasikan prototype yang menggabungkan JavaScript V8 dengan event loop non-blocking. Sebelumnya, JavaScript hanya hidup di browser. Node.js memindahkannya ke server dengan memanfaatkan dua teknologi kunci:
Pada tahun 2010 muncul npm — registry paket yang mengubah cara pengembang berbagi kode. Hari ini npm adalah ekosistem paket terbesar di dunia, dan Node.js menjadi fondasi banyak tool modern seperti Next.js, Vite, dan seluruh toolchain frontend kalian.
Perbedaan kunci antara kanal rilis: versi current hanya didukung hingga rilis berikutnya tiba, sementara versi LTS mendapat dukungan aktif selama bertahun-tahun. Pilih LTS untuk server produksi dan current hanya jika kalian sengaja mencoba fitur terbaru.
Sejak tahun 2015, Node.js mengadopsi rilis berjadwal dengan kanal LTS (Long-Term Support) yang stabil untuk produksi. Versi 20, 22, dan 24 adalah deretan rilis LTS terbaru — dukungan keamanan aktif selama bertahun-tahun, sehingga tim backend bisa memakai Node.js dengan percaya diri.
node --version
node -p "process.release.lts"Perintah node -p "process.release.lts" mencetak nama codename LTS. Jika null, berarti kalian memakai rilis non-LTS — tidak masalah untuk eksperimen, tapi untuk produksi pilih versi LTS.
Model klasik server web mengalokasikan satu thread per koneksi. Semakin banyak koneksi, semakin banyak memori dan thread yang habis. Node.js mengambil pendekatan berbeda: satu thread utama menjalankan JavaScript, sementara operasi I/O yang lambat — baca file, koneksi jaringan, query database — dilepaskan ke libuv dan diproses di luar thread utama.
Karena itu Node.js sangat efisien untuk workload yang I/O-bound, seperti API, proxy, dan real-time messaging. Istilah pentingnya: non-blocking I/O, di mana kode tidak berhenti menunggu operasi selesai. Istilah lain yang sering muncul adalah backpressure — ketika produksi data lebih cepat dari konsumsinya, data menumpuk dan aliran harus diperlambat. Node.js menangani ini lewat buffer stream yang akan kita bahas di episode 5.
Sebaliknya, workload yang CPU-bound — hashing, kompresi, pemrosesan gambar — tidak otomatis mendapat manfaat dari model ini. Operasi semacam itu tetap berjalan di thread utama dan bisa menghentikan semuanya; strategi menanganinya akan kita bahas di episode 19.
Event loop adalah mekanisme yang memproses operasi secara bergiliran: ambil callback dari queue, jalankan sampai selesai, lalu lanjut ke callback berikutnya. Diagram sederhananya seperti ini:
operasi selesai -> callback masuk queue -> event loop menjalankan callbackKarena hanya satu thread yang menjalankan JavaScript, blocking di satu tempat menghentikan semuanya. Inilah alasan praktik seperti fs.readFileSync tidak disarankan di server produksi — episode 5 dan 19 akan membahas ini lebih dalam.
Event loop berjalan dalam beberapa fase yang diulang terus-menerus: timers, pending callbacks, poll, check, dan close callbacks. setTimeout diproses di fase timers, I/O jaringan di fase poll, dan setImmediate di fase check. Kalian tidak perlu menghafal semua fase sekarang — yang penting paham bahwa operasi dijadwalkan, bukan dijalankan langsung — tapi detail fase ini akan kita bedah bersama profiling di episode 19.
Coba bandingkan dua versi kode berikut. Versi pertama memakai readFileSync yang memblokir thread utama:
const fs = require("fs");
const data = fs.readFileSync("/tmp/contoh.txt", "utf8");
console.log(data);
console.log("Selesai setelah file dibaca");Versi kedua memakai readFile yang non-blocking:
const fs = require("fs");
fs.readFile("/tmp/contoh.txt", "utf8", (err, data) => {
if (err) throw err;
console.log(data);
});
console.log("Selesai tanpa menunggu file dibaca");Pada versi non-blocking, pesan Selesai tanpa menunggu muncul lebih dulu karena fungsi callback dijadwalkan ke event loop. Pola ini — meneruskan fungsi sebagai callback — adalah ciri khas Node.js yang akan kalian temui di hampir setiap modul. Callback di dalam callback juga melahirkan istilah callback hell, dan solusinya berupa Promise yang akan kalian pakai sejak episode 4.
Perhatikan juga bentuk callback bawaan Node.js: argumen pertama selalu err, dan argumen berikutnya adalah data hasil operasi. Inilah konvensi error-first callback yang dipakai seluruh API asinkron di Node.js. Dengan konvensi ini, error tidak lagi bergantung pada try-catch biasa, karena operasi asinkron selesai setelah thread utama sudah bergerak maju — callbacklah yang menerima kabar hasil atau kegagalan.
Kinerja Node.js sebagian besar berasal dari V8. V8 meng-compile JavaScript langsung ke machine code dengan teknik JIT (just-in-time compilation) yang terus dioptimalkan. Update V8 otomatis ikut naik ke Node.js setiap rilis, sehingga aplikasi kalian mendapat optimasi terbaru tanpa mengubah kode.
Ekosistem Node.js tidak akan selengkap sekarang tanpa npm. Dengan satu perintah, kalian bisa menambahkan library matang seperti Express, Prisma, atau Redis client. Kita baru akan memakainya secara intensif di episode 2 dan seterusnya, tapi sudah saatnya kalian paham posisi npm sebagai pusat distribusi paket.
npm mencatat seluruh dependensi di package.json dan menguncinya dalam package-lock.json. File lock inilah yang membuat npm ci bekerja secara deterministik di episode 21, memastikan semua orang — dari laptop pengembang sampai pipeline CI — memasang dependensi yang persis sama. Kebiasaan memperlakukan lockfile sebagai bagian dari kode adalah ciri tim yang rapi.
Inti yang harus dibawa pulang:
Di episode 2 selanjutnya kita akan membahas instalasi, node, npm, dan npx — cara kerja ketiga perintah tersebut, struktur package.json, semver, serta kapan memakai npx untuk menjalankan tool tanpa install global. Pastikan Node.js sudah terpasang, karena kita mulai banyak mengetik di terminal.