Framework frontend seperti React, Vue, dan Svelte tidak menggantikan bekal jalur ini, melainkan membangun di atasnya. Komponen tetap berupa fungsi, state tetap berupa variabel, dan event tetap ditangani dengan pola listener yang sama, hanya saja framework mengambil alih pekerjaan yang paling berulang, yaitu menyinkronkan data dengan tampilan. Topik ini memetakan konsep-konsep itu ke tiga framework populer secara netral, lalu menimbang kapan framework menguntungkan dan kapan vanilla JavaScript masih cukup.
Masalah yang dipecahkan framework#
Setiap perubahan data pada aplikasi vanilla harus disalin ke tampilan dengan tangan, memperbarui textContent, mengganti class, atau membangun ulang elemen. Semakin banyak bagian tampilan bergantung pada data yang sama, semakin mudah satu pembaruan terlewat dan tampilan menjadi tidak sinkron dengan datanya. Framework menghapus pekerjaan itu dengan satu ide, tampilan dinyatakan sebagai fungsi dari data, lalu framework sendiri yang menghitung bagian mana yang perlu digambar ulang saat data berubah.
Model tersebut menjadikan konsep-konsep jalur ini tulang punggungnya. Komponen adalah fungsi yang mengembalikan tampilan, state adalah variabel yang diperhatikan framework, dan efek samping seperti fetch ditangani pada momen siklus hidup (lifecycle) komponen. Yang berubah hanya siapa yang memantau perubahan data, bukan cara JavaScript bekerja, sehingga pemahaman event, closure, dan promise tetap terpakai penuh.
Peta konsep ke React, Vue, dan Svelte#
Tiga framework itu menyebut konsep yang sama dengan nama berbeda, dan tabel berikut memetakannya ke bekal yang sudah dibangun. Istilah pada tabel hanya contoh yang paling umum, dan setiap framework menawarkan bentuk lain di samping yang tercantum.
| Bekal dari jalur ini | React | Vue | Svelte |
|---|---|---|---|
| Komponen sebagai fungsi | function component | single-file component | berkas .svelte |
| Variabel yang memicu pembaruan tampilan | useState | ref() dan reactive() | rune $state |
| Respons atas event | properti onClick | arahan @click | arahan on:click |
| Efek samping terjadwal | useEffect | watch() dan onMounted | rune $effect |
Yang perlu diperhatikan dari tabel itu bukan nama-namanya, melainkan kesamaan polanya. Ketiganya menjawab pertanyaan yang sama, bagaimana variabel memicu pembaruan, bagaimana event dihubungkan ke fungsi, dan kapan efek samping dijalankan. Nama-nama pada tabel juga berlaku sepanjang dokumentasi resmi ketiganya, sehingga pembaca yang melanjutkan ke dokumentasi React, Vue, atau Svelte akan bertemu istilah yang sama pada halaman pertamanya. Tabel ini sekaligus menjadi pemeriksa cepat saat membaca kode framework milik orang lain. Karena polanya sama, kebiasaan memecah masalah menjadi fungsi kecil yang telah dilatih sepanjang jalur ini berlaku sama baiknya di framework mana pun yang dipilih belakangan.
Penghitung vanilla sebagai pembanding#
Demo berikut adalah penghitung sederhana tanpa framework apa pun, tombol Tambah menaikkan angka dan tombol Nol-kan mengembalikannya ke nol. Coba keduanya pada demo di bawah, lalu perhatikan bahwa setiap perubahan data disalin ke tampilan secara manual di dalam handler.
Kode sumber demo
<!DOCTYPE html>
<html lang="id">
<head>
<meta charset="utf-8">
<title>Penghitung vanilla</title>
<style>
body { font-family: sans-serif; text-align: center; padding-top: 16px; }
#nilai { font-size: 2rem; margin: 8px 0 16px; }
button { padding: 6px 14px; margin: 0 4px; font-size: 1rem; }
</style>
</head>
<body>
<p id="nilai">0</p>
<button id="tambah" type="button">Tambah</button>
<button id="nolkan" type="button">Nol-kan</button>
<script src="index.js"></script>
<script>
// State berupa satu variabel, setiap perubahan disalin manual ke tampilan.
let angka = 0;
const tampil = document.getElementById("nilai");
const tombolTambah = document.getElementById("tambah");
const tombolNolkan = document.getElementById("nolkan");
tombolTambah.addEventListener("click", () => {
angka += 1;
tampil.textContent = angka;
});
tombolNolkan.addEventListener("click", () => {
angka = 0;
tampil.textContent = angka;
});
</script>
<script>
// State berupa satu variabel, setiap perubahan disalin manual ke tampilan.
let angka = 0;
const tampil = document.getElementById("nilai");
const tombolTambah = document.getElementById("tambah");
const tombolNolkan = document.getElementById("nolkan");
tombolTambah.addEventListener("click", () => {
angka += 1;
tampil.textContent = angka;
});
tombolNolkan.addEventListener("click", () => {
angka = 0;
tampil.textContent = angka;
});
</script></body>
</html>Struktur halamannya berdiri sendiri dalam satu berkas HTML tanpa CDN maupun langkah build.
<!DOCTYPE html>
<html lang="id">
<head>
<meta charset="utf-8">
<title>Penghitung vanilla</title>
<style>
body { font-family: sans-serif; text-align: center; padding-top: 16px; }
#nilai { font-size: 2rem; margin: 8px 0 16px; }
button { padding: 6px 14px; margin: 0 4px; font-size: 1rem; }
</style>
</head>
<body>
<p id="nilai">0</p>
<button id="tambah" type="button">Tambah</button>
<button id="nolkan" type="button">Nol-kan</button>
<script src="index.js"></script>
</body>
</html>Pada index.js, baris tampil.textContent = angka adalah pekerjaan sinkronisasi yang dimaksud di bagian pertama, dan baris semacam itulah yang dihapus framework. Penghitung yang sama di React dinyatakan dengan useState lalu angkanya ditulis langsung pada markah, sedangkan di Svelte cukup satu variabel dengan rune $state yang ikut tergambar ulang setiap nilainya berubah. Tidak ada baris yang menyalin data ke tampilan, karena framework yang menjadwalkan pembaruannya. Untuk dua tombol, selisihnya kecil, dan versi vanilla tetap menjadi pilihan yang wajar.
Kapan framework menguntungkan#
Keduanya punya wilayah yang wajar, dan pilihannya lebih mengikuti bentuk aplikasinya daripada kepopulerannya. Beberapa petunjuk yang biasa dipakai:
- Framework menguntungkan ketika tampilan dibangun dari banyak komponen yang berbagi state sama, misalnya daftar catatan yang dapat disunting, difilter, dan ditandai dari beberapa tempat berbeda.
- Framework menguntungkan ketika timnya besar, karena struktur komponen dan kebiasaan yang ditetapkan framework membuat kode orang lain lebih mudah dibaca dan dipelihara.
- Vanilla cukup ketika interaksinya sedikit, halaman didominasi konten statis, atau skripnya berdiri sendiri, misalnya satu form dan widget kecil.
- Vanilla cukup ketika anggaran ukuran halaman ketat, karena tanpa framework tidak ada runtime tambahan yang dikirim ke browser.
Tidak ada keunggulan mutlak di antara React, Vue, dan Svelte, ketiganya matang, terawat, dan dipakai luas, sehingga perbedaannya lebih terasa pada kebiasaan penulisannya daripada hasil akhirnya. Bila wilayahnya mulai melewati vanilla, pindah ke framework bukan berarti membuang bekal yang ada. Justru saat itulah fungsi, closure, promise, dan DOM yang sudah dikuasai bekerja paling terasa, karena framework itu sendiri dibangun dari konsep yang sama.
Ringkasan#
- Framework mengambil alih sinkronisasi data ke tampilan, pekerjaan yang pada vanilla dilakukan manual lewat DOM.
- Konsep intinya sama di React, Vue, dan Svelte, yaitu komponen, state reaktif, penanganan event, dan efek samping terjadwal.
- Demo penghitung vanilla memperlihatkan baris sinkronisasi manual yang justru dihapus framework.
- Pilihan framework mengikuti bentuk aplikasinya, banyak komponen yang berbagi state mendukung framework, sedangkan interaksi yang sedikit cukup dengan vanilla.
Referensi#
- Learn React — react.dev — panduan resmi React tentang komponen, state, dan efek.
- Introduction — Vue.js — gambaran resmi model komponen dan reaktivitas Vue.
- Svelte overview — Svelte
— dokumentasi resmi Svelte, termasuk rune
$statedan$effect. - Document Object Model (DOM) — MDN Web Docs — fondasi manipulasi tampilan yang tetap bekerja di balik framework.