Referensi lengkap Svelte 5 dengan Runes. State management, reactivity, components, dan fitur modern Svelte. Performa mantap!
Cara memulai menggunakan Svelte untuk membuat aplikasi web dengan performa tinggi.
Langkah-langkah untuk menginstall dan menjalankan Svelte.
# Create new project
npm create svelte@latest my-app
# Install dependencies
cd my-app
npm install
# Start dev server
npm run devStruktur dasar komponen Svelte dengan script, markup, dan styling.
<script>
let count = 0
function increment() {
count += 1
}
</script>
<button on:click={increment}>
Count: {count}
</button
Fitur baru di Svelte 5 untuk state management dan reactivity yang lebih powerful.
Cara membuat reactive state di Svelte 5 menggunakan rune $state.
<script>
// Reactive state (Svelte 5)
let count = $state(0)
let user = $state({ name: 'Budi', age: 25 })
function increment() {
count
<script>
let count = $state(0)
// Derived state (auto-computed)
let doubled = $derived(count * 2)
let message = $
<script>
let count = $state(0)
// Run side effects
$effect(() => {
console.log(`Count is now ${count}`)
<script>
// Declare props (Svelte 5)
let { title, count = 0, user } = $props()
// Dengan fallback
let { name = 'Guest' } = $props()
// Rest props
let
<!-- Child.svelte -->
<script>
// Bindable prop (two-way binding)
let { value = $bindable() } = $props()
</script>
<input bind:value />
<!-- Parent.svelte -->
<script>
let count = 0
// Reactive statement
$: doubled = count * 2
$: console.log('Count changed:', count)
// Reactive block
$: {
console.
<script>
let count = 0
let history = []
// Update reactively
function increment() {
count += 1
history = [...history, count] // Trigger reactivity
<script>
let name = 'Budi'
let count = 5
</script>
<!-- Text interpolation -->
<p>{name}</p>
<p>{count + 1}</p
<script>
let user = { loggedIn: false }
let count = 5
</script>
<!-- if -->
{#if user.loggedIn}
<p>Welcome back!</p>
<script>
let items = [
{ id: 1, name: 'Apple' },
{ id: 2, name: 'Banana' },
{ id: 3, name: 'Orange' }
]
<script>
async function fetchData() {
const response = await fetch('/api/data')
return response.json()
}
let promise = fetchData()
<script>
function handleClick() {
console.log('Clicked!')
}
function handleInput(event) {
console.log(event.target.value)
}
</
<!-- Prevent default -->
<form on:submit|preventDefault={handleSubmit}>
<!-- Stop propagation -->
<button on:click|stopPropagation={handleClick}>
<!-- Only once -->
<script>
let name = ''
let message = ''
let checked = false
let selected = ''
<!-- Child.svelte -->
<script>
export let value
</script>
<input bind:value />
<!-- Parent.svelte -->
<script>
let text = ''
</script
<script>
let div
let input
$: console.log(div) // DOM element
</script>
<div bind:this={div}>Content</div>
<input
<!-- Button.svelte -->
<script>
// Props (classic way)
export let variant = 'primary'
export let disabled = false
// Svelte 5 way
let { variant = 'primary', disabled = false }
<script>
import Button from './Button.svelte'
</script>
<Button variant="primary">Click me</Button>
<Button variant="secondary" disabled>Disabled</Button><!-- Card.svelte -->
<div class="card">
<div class="header">
<slot name="header" />
</div>
<div class=
<!-- List.svelte -->
<script>
export let items
</script>
{#each items as item}
<slot item={item} />
{/each}
<!-- Usage -->
<List items
<script>
import { onMount, onDestroy, beforeUpdate, afterUpdate } from 'svelte'
onMount(() => {
console.log('Component mounted')
// Return cleanup function
return () => {
console.
<script>
// Use $effect instead
$effect(() => {
console.log('Mounted / Updated')
return () => {
console.log('Cleanup')
}
})
</script// stores.js
import { writable } from 'svelte/store'
export const count = writable(0)
export const user = writable({
name: 'Budi',
email: 'budi@example.com'
})<script>
import { count } from './stores.js'
// Subscribe with $
// Auto-subscribe dan auto-unsubscribe
$count
// Update
function increment() {
count.update(n => n + 1
import { readable } from 'svelte/store'
export const time = readable(new Date(), set => {
const interval = setInterval(() => {
set(new Date())
import { derived } from 'svelte/store'
import { count } from './stores.js'
export const doubled = derived(
count,
$count => $count * 2
)
// Multiple stores
export const
import { writable } from 'svelte/store'
function createCounter() {
const { subscribe, set, update } = writable(0)
return {
subscribe,
increment: ()
<script>
import { fade, fly, slide, scale } from 'svelte/transition'
let visible = true
</script>
{#if visible}
<div transition:fade>Fade in/out</
<script>
import { fly, fade } from 'svelte/transition'
</script>
<div
transition:fly={{
y: 200,
duration: 500,
delay: 100,
easing: cubicOut
function typewriter(node, { speed = 1 }) {
const valid = node.childNodes.length === 1 && node.childNodes[0].nodeType === Node.TEXT_NODE
if (!
<script>
import { flip } from 'svelte/animate'
import { quintOut } from 'svelte/easing'
let items = [1, 2, 3, 4, 5]
<script>
function clickOutside(node) {
function handleClick(event) {
if (!node.contains(event.target)) {
node.dispatchEvent(new CustomEvent
src/routes/
├── +page.svelte # /
├── about/
│ └── +page.svelte # /about
├── blog/
│ ├── +page.svelte # /blog
│ └── [slug]/
│ └── +page.svelte # /blog/[slug]
└── api/
└── users/
└── +server.js # /api/users// +page.js
export async function load({ fetch, params }) {
const response = await fetch('/api/users')
const users = await response.json()
return {
users
<!-- +page.svelte -->
<script>
export let data
</script>
<h1>Users</h1>
{#each data.users as user}
<p>{user.name}</p>
{/each}// +page.server.js
export const actions = {
default: async ({ request }) => {
const data = await request.formData()
const email = data.get('email'
<!-- +page.svelte -->
<script>
export let form
</script>
<form method="POST">
<input name="email" type="email" />
<button
<!-- Bad -->
<script>
let items = []
items.push(newItem) // Won't trigger reactivity
</script>
<!-- Good -->
<script>
let items = []
items = [
<!-- Bad -->
<script>
export let user
user.name = 'Ani' // Mutating prop
</script>
<!-- Good -->
<script>
export let user
let localUser = { ...
<!-- Bad - no key -->
{#each items as item}
<div>{item.name}</div>
{/each}
<!-- Bad - index as key -->
{#each items as item, i (i)}
<div>{item.name}</div>