Ringkasan Utama
Svelte 5, dirilis Oktober 2024, mengganti reaktivitas implisit bawaan compiler dengan runes: simbol eksplisit seperti $state, $derived, $effect, dan $props yang menandai nilai reaktif. Di baliknya, Svelte memakai signals untuk pembaruan fine-grained, dan runes bekerja di modul .svelte.js dan .svelte.ts, sehingga developer bisa berbagi logika reaktif di luar komponen.
Selama bertahun-tahun, keunggulan utama Svelte adalah reaktivitas yang terlihat seperti tidak ada apa-apanya. Anda menulis let count = 0 biasa, menetapkannya ulang, dan UI ikut diperbarui. Sebuah let di level atas komponen bersifat reaktif secara implisit, dan label dolar-titik dua mengubah pernyataan apa pun menjadi derivasi yang berjalan ulang. Terasa ajaib saat pertama kali, dan membingungkan pada kali kesepuluh, karena apakah sebuah variabel reaktif bergantung pada di mana ia ditulis, bukan pada sesuatu yang terlihat di baris itu sendiri.
Svelte 5, dirilis stabil pada Oktober 2024, mempertahankan output yang dikompilasi habis tetapi membuang aturan implisitnya. Reaktivitas kini dideklarasikan dengan runes — simbol eksplisit yang bisa dibaca sekilas. Saya sudah cukup banyak mengirim komponen Svelte hingga pernah terjebak model lama, jadi pertukaran sedikit lebih banyak mengetik demi kejelasan yang jauh lebih besar ini saya sambut baik.
Apa sebenarnya sebuah rune
Dokumentasi resmi mendefinisikan runes sebagai simbol yang Anda gunakan di file .svelte dan .svelte.js atau .svelte.ts untuk mengendalikan compiler Svelte. Runes memakai awalan tanda dolar dan tampak seperti pemanggilan fungsi, tetapi bukan fungsi: Anda tidak mengimpornya, tidak bisa menyimpannya dalam variabel atau meneruskannya sebagai argumen, dan hanya bekerja di posisi tertentu. Runes adalah kata kunci dalam bahasa Svelte, divalidasi oleh compiler.
Kumpulan intinya kecil. $state mendeklarasikan state reaktif, $derived menghitung nilai dari state lain, $effect menjalankan efek samping saat dependensi berubah, dan $props mendeklarasikan input yang diterima komponen dari induknya. Ada beberapa lagi — $bindable, $inspect, $host — tetapi keempat itulah yang menopang hampir semua komponen yang akan Anda tulis.
Empat runes yang akan Anda pakai setiap hari
$state adalah titik awal. Anda menulis let count = $state(0) dan, seperti kata dokumentasi, count hanyalah sebuah angka, bukan objek atau fungsi, dan Anda bisa memperbaruinya seperti variabel lain mana pun. Untuk array dan objek biasa, $state mengembalikan proxy yang reaktif secara mendalam, sehingga memutasi field bersarang atau memanggil push tetap terlacak. $derived menerima ekspresi yang harus bebas efek samping dan menghitung ulang setiap dependensinya berubah; $effect berjalan setelah komponen ter-mount dan berjalan ulang dalam sebuah microtask setelah state yang dibacanya berubah.
<script>
// $state declares reactive state — count is just a number
let count = $state(0);
// $derived recomputes automatically when count changes
let doubled = $derived(count * 2);
// $effect runs after mount and re-runs when its deps change
$effect(() => {
console.log('count is now', count);
});
</script>
<button onclick={() => count++}>
clicks: {count} (doubled: {doubled})
</button>Contoh di atas menunjukkan ketiganya bekerja sama. count adalah state reaktif, doubled diturunkan darinya dan tidak pernah ditetapkan manual, dan effect mencatat log setiap count berubah. Perhatikan tidak ada pemanggilan subscribe dan tidak ada array dependensi — Svelte melacak state mana yang dibaca tiap derivasi dan effect, lalu menjalankan ulang tepat yang bergantung pada apa yang berubah.
Utamakan $derived daripada $effect untuk apa pun yang menghitung sebuah nilai. Dokumentasi memperingatkan bahwa Anda umumnya tidak boleh memperbarui state di dalam effect, karena membuat kode berbelit dan sering memicu siklus pembaruan tanpa akhir. Jika Anda mendapati diri menulis effect yang menetapkan state lain, itu hampir selalu nilai turunan yang menyamar.
Mengapa tim meninggalkan sihirnya
Perpindahan ini bukan sekadar tren. Tim Svelte menjelaskan bahwa di Svelte 4, jika Anda mengubah satu properti dari sebuah objek reaktif, seluruh objek dinyatakan tidak valid, karena hanya itu yang realistis bisa dilakukan compiler. Sementara itu framework lain mengadopsi reaktivitas fine-grained berbasis signals dan melampaui performa Svelte. Pernyataan dolar-titik dua lama juga mencampur dua konsep — state turunan dan efek samping — yang seharusnya dipisah. Runes memisahkan keduanya dan membiarkan compiler merangkai pembaruan fine-grained berbasis signal alih-alih membatalkan seluruh objek.
Runes adalah kata kunci yang bergantung posisi, bukan nilai. Anda tidak bisa menulis const r = $state atau meneruskan $derived ke fungsi bantuan — compiler menolaknya. Jika sebuah aturan lint atau rekan tim menyarankan mengekstrak rune ke utilitas bersama, langkah yang benar adalah modul .svelte.js yang mengembalikan getter reaktif, bukan variabel yang menyimpan rune itu sendiri.
Reaktivitas yang keluar dari komponen
Perubahan yang diam-diam paling penting adalah reaktivitas universal. Karena runes adalah fitur compiler dan bukan fitur komponen, runes juga bekerja di modul .svelte.js dan .svelte.ts. Artinya Anda bisa menulis logika reaktif yang dapat dipakai ulang sekali saja dan mengimpornya di mana pun, memakai satu mekanisme alih-alih API stores lama.
// counter.svelte.js — universal reactivity outside components
export function createCounter() {
let count = $state(0);
return {
get count() { return count; },
increment: () => count += 1,
reset: () => count = 0,
};
}
// any .svelte component can now import and use this:
// import { createCounter } from './counter.svelte.js';
// const counter = createCounter();Di Svelte 4, berbagi state reaktif antarkomponen berarti memakai writable stores beserta subscribe atau akses berawalan dolar. Dengan runes Anda bisa menyatakan hal yang sama sebagai JavaScript biasa yang kebetulan reaktif, mengekspos state melalui getter. Stores tetap ada dan tetap punya tempatnya, tetapi untuk kebanyakan logika bersama, modul .svelte.js kini menjadi pilihan default yang lebih sederhana.
Migrasi dari Svelte 4
Model mentalnya memetakan dengan rapi, dan ada jalur otomatis. Menjalankan perintah migrasi akan meningkatkan dependensi inti dan menulis ulang sebagian besar sintaks lama untuk Anda, meski beberapa pembersihan manual tetap tersisa. Substitusi utamanya adalah:
- let reaktif implisit menjadi $state — sebuah variabel reaktif hanya ketika dibuat dengan rune-nya.
- Derivasi dolar-titik dua menjadi $derived; efek samping dolar-titik dua menjadi $effect — dua tanggung jawab yang dulu dicampur sintaks lama kini menjadi runes terpisah.
- export let untuk props menjadi satu destrukturisasi $props, dengan default, penggantian nama, dan rest props diungkapkan di satu tempat.
- Jalankan npx sv migrate svelte-5 untuk menaikkan dependensi, mengonversi let ke $state, mengganti on:click menjadi onclick, serta mengubah slot menjadi snippet dan render tag.
Svelte 4 versus runes Svelte 5
| Aspek | Svelte 4 | Runes Svelte 5 |
|---|---|---|
| Mendeklarasikan state | Implisit — let level atas mana pun | Eksplisit — let x = $state(...) |
| Nilai turunan | Pernyataan reaktif dolar-titik dua | Ekspresi $derived |
| Efek samping | Juga dolar-titik dua — sintaks sama dengan derivasi | $effect — dipisahkan dari derivasi |
| Props komponen | export let per properti | Satu destrukturisasi $props |
| Reaktivitas di luar komponen | Writable dan readable stores | Runes di modul .svelte.js dan .svelte.ts |
Saran saya, mulailah fitur baru dengan runes alih-alih mengonversi seluruh aplikasi di hari pertama. Kejelasannya paling cepat terasa pada kode yang sedang aktif Anda ubah, tempat mengetahui sekilas nilai mana yang reaktif menghilangkan satu kelas bug. Jalankan skrip migrasi di sebuah branch, baca diff-nya, dan perlakukan perbaikan manual yang tersisa sebagai kesempatan mempelajari di mana sihir lama itu bersembunyi.

