Runes Svelte 5: Reaktivitas $state, $derived, $effect

Foto oleh Chris Ried on Unsplash
Runes adalah simbol berawalan tanda dolar yang Anda gunakan di file .svelte, .svelte.js, dan .svelte.ts untuk mengendalikan compiler Svelte. Runes tampak seperti pemanggilan fungsi tetapi merupakan kata kunci, jadi tidak diimpor, tidak bisa disimpan dalam variabel, dan hanya bisa dipakai di posisi tertentu. Kumpulan intinya adalah $state, $derived, $effect, dan $props.
Di Svelte 4 compiler membatalkan seluruh objek saat satu properti berubah, dan sintaks dolar-titik dua mencampur state turunan dengan efek samping. Runes membuat reaktivitas eksplisit dan membiarkan compiler merangkai pembaruan fine-grained berbasis signals, menutup jarak performa dengan framework berbasis signal lain. Svelte 5 dirilis stabil pada Oktober 2024.
$derived menghitung nilai dari state reaktif lain dan harus bebas efek samping, menghitung ulang otomatis saat dependensinya berubah. $effect menjalankan efek samping setelah komponen ter-mount dan berjalan ulang saat state yang dibacanya berubah. Dokumentasi menyarankan tidak memperbarui state di dalam effect karena memicu kode berbelit dan siklus tanpa akhir; pakai $derived untuk nilai terhitung.
Bisa. Karena runes adalah fitur compiler dan bukan fitur komponen, runes bekerja di modul .svelte.js dan .svelte.ts. Reaktivitas universal ini memungkinkan Anda menulis logika reaktif yang dapat dipakai ulang sekali dan mengimpornya di mana pun, mengekspos state melalui getter, yang untuk kebanyakan logika bersama menggantikan API writable stores lama.
Jalankan npx sv migrate svelte-5. Perintah ini menaikkan dependensi inti, mengonversi let reaktif implisit ke $state, menulis ulang pernyataan dolar-titik dua menjadi $derived atau $effect, memigrasi atribut event seperti on:click ke onclick, dan mengubah slot menjadi snippet dan render tag. Beberapa pembersihan manual tetap tersisa, jadi tinjau diff-nya di sebuah branch.

Foto oleh Chris Ried on Unsplash
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.
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.
$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.
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.
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.
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:
| 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.