BelajarKoding Logobelajarkoding

Platform belajar web development Indonesia. Artikel, cheat sheets, roadmap, dan code challenges untuk developer Indonesia.

Navigasi

  • Artikel
  • Cheat Sheets
  • Roadmap
  • Challenges
  • Pricing
  • Search

Produk Lain

  • JagoHermes
  • KelasClaude
  • KilatKoding
  • BelajarVibeCoding
  • JualanKoding

Support

  • Privacy Policy
  • Terms of Service
  • Email

© 2026 BelajarKoding. All rights reserved.

Galih PratamaBagian dari ekosistem Galih Pratama
belajarkoding LogobyGalih Pratama
RoadmapArtikelCheat SheetsChallengesUpgrade
belajarkoding LogobyGalih Pratama
RoadmapArtikelCheat SheetsChallengesUpgrade
belajarkoding LogobyGalih Pratama
RoadmapArtikelCheat SheetsChallengesUpgrade

Daftar Isi

Getting StartedInstallationBasic ComponentSvelte 5 Runes$state$derived$effect$props$bindableReactivity (Classic)Reactive DeclarationsReactive AssignmentsTemplate SyntaxExpressionsConditional RenderingList RenderingAwait BlocksEventsEvent HandlersEvent ModifiersBindingsInput BindingsComponent BindingsElement BindingsComponentsDefining ComponentsUsing ComponentsSlotsSlot PropsLifecycleClassic LifecycleSvelte 5 LifecycleStoresWritable StoreUsing StoresReadable StoreDerived StoreCustom StoresTransitionsBuilt-in TransitionsTransition ParametersCustom TransitionsAnimationsActionsSvelteKitRoutesLoad FunctionsForm ActionsBest PracticesReactivityComponent PropsKeys in Lists
SvelteJavaScriptFrontend

Svelte 5 Cheat Sheet

Referensi lengkap Svelte 5 dengan Runes. State management, reactivity, components, dan fitur modern Svelte. Performa mantap!

JavaScript10 min read1.989 kata
Silakan login atau daftar untuk membaca cheat sheet ini.

#Getting Started

Cara memulai menggunakan Svelte untuk membuat aplikasi web dengan performa tinggi.

#Installation

Langkah-langkah untuk menginstall dan menjalankan Svelte.

bash
# Create new project
npm create svelte@latest my-app
 
# Install dependencies
cd my-app
npm install
 
# Start dev server
npm run dev

#Basic Component

Struktur dasar komponen Svelte dengan script, markup, dan styling.

svelte
<script>
 let count = 0
 
 function increment() {
  count += 1
 }
</script>
 
<button on:click={increment}>
 Count: {count}
</button>
 
<style>
 button {
  background: blue;
  color: white;
 }
</style>

#Svelte 5 Runes

Fitur baru di Svelte 5 untuk state management dan reactivity yang lebih powerful.

#$state

Cara membuat reactive state di Svelte 5 menggunakan rune $state.

svelte
<script>
 // Reactive state (Svelte 5)
 let count = $state(0)
 let user = $state({ name: 'Budi', age: 25 })
 
 function increment() {
  count += 1
 }
 
 function updateName() {
  user.name = 'Ani'
 }
</script>
 
<button on:click={increment}>
 {count}
</button>
 
<p>{user.name}</p>

#$derived

svelte
<script>
 let count = $state(0)
 
 // Derived state (auto-computed)
 let doubled = $derived(count * 2)
 let message = $derived(`Count is ${count}`)
 
 // Derived dengan complex logic
 let status = $derived(() => {
  if (count < 5) return 'low'
  if (count < 10) return 'medium'
  return 'high'
 })
</script>
 
<p>Count: {count}</p>
<p>Doubled: {doubled}</p>
<p>Status: {status}</p>

#$effect

svelte
<script>
 let count = $state(0)
 
 // Run side effects
 $effect(() => {
  console.log(`Count is now ${count}`)
 })
 
 // Effect dengan cleanup
 $effect(() => {
  const interval = setInterval(() => {
   count += 1
  }, 1000)
 
  return () => {
   clearInterval(interval)
  }
 })
 
 // Pre-effect (runs before DOM updates)
 $effect.pre(() => {
  console.log('Before update')
 })
 
 // Root effect (no auto-tracking)
 $effect.root(() => {
  console.log('This runs once')
 })
</script>

#$props

svelte
<script>
 // Declare props (Svelte 5)
 let { title, count = 0, user } = $props()
 
 // Dengan fallback
 let { name = 'Guest' } = $props()
 
 // Rest props
 let { class: className, ...rest } = $props()
</script>
 
<h1>{title}</h1>
<p>{count}</p>

#$bindable

svelte
<!-- Child.svelte -->
<script>
 // Bindable prop (two-way binding)
 let { value = $bindable() } = $props()
</script>
 
<input bind:value />
 
<!-- Parent.svelte -->
<script>
 let text = $state('')
</script>
 
<Child bind:value={text} />
<p>{text}</p>

#Reactivity (Classic)

#Reactive Declarations

svelte
<script>
 let count = 0
 
 // Reactive statement
 $: doubled = count * 2
 $: console.log('Count changed:', count)
 
 // Reactive block
 $: {
  console.log('Count is', count)
  if (count > 10) {
   console.log('Too high!')
  }
 }
 
 // Reactive array
 let numbers = [1, 2, 3]
 $: sum = numbers.reduce((a, b) => a + b, 0)
</script>

#Reactive Assignments

svelte
<script>
 let count = 0
 let history = []
 
 // Update reactively
 function increment() {
  count += 1
  history = [...history, count] // Trigger reactivity
 }
 
 // Array methods that DON'T trigger reactivity
 function badPush() {
  history.push(count) // Won't trigger update
 }
 
 // Fix dengan assignment
 function goodPush() {
  history.push(count)
  history = history // Trigger reactivity
 }
</script>

#Template Syntax

#Expressions

svelte
<script>
 let name = 'Budi'
 let count = 5
</script>
 
<!-- Text interpolation -->
<p>{name}</p>
<p>{count + 1}</p>
<p>{name.toUpperCase()}</p>
 
<!-- Raw HTML (hati-hati XSS!) -->
<div>{@html htmlString}</div>
 
<!-- Debug -->
{@debug count, name}

#Conditional Rendering

svelte
<script>
 let user = { loggedIn: false }
 let count = 5
</script>
 
<!-- if -->
{#if user.loggedIn}
 <p>Welcome back!</p>
{/if}
 
<!-- if-else -->
{#if count > 10}
 <p>High</p>
{:else}
 <p>Low</p>
{/if}
 
<!-- if-else if-else -->
{#if count < 5}
 <p>Low</p>
{:else if count < 10}
 <p>Medium</p>
{:else}
 <p>High</p>
{/if}

#List Rendering

svelte
<script>
 let items = [
  { id: 1, name: 'Apple' },
  { id: 2, name: 'Banana' },
  { id: 3, name: 'Orange' }
 ]
</script>
 
<!-- Basic loop -->
{#each items as item}
 <p>{item.name}</p>
{/each}
 
<!-- With index -->
{#each items as item, index}
 <p>{index + 1}. {item.name}</p>
{/each}
 
<!-- With key (important!) -->
{#each items as item (item.id)}
 <p>{item.name}</p>
{/each}
 
<!-- Destructuring -->
{#each items as { id, name }}
 <p>{name}</p>
{/each}
 
<!-- With else -->
{#each items as item}
 <p>{item.name}</p>
{:else}
 <p>No items</p>
{/each}

#Await Blocks

svelte
<script>
 async function fetchData() {
  const response = await fetch('/api/data')
  return response.json()
 }
 
 let promise = fetchData()
</script>
 
{#await promise}
 <p>Loading...</p>
{:then data}
 <p>Got {data.length} items</p>
{:catch error}
 <p>Error: {error.message}</p>
{/await}
 
<!-- Short form -->
{#await promise then data}
 <p>{data}</p>
{/await}

#Events

#Event Handlers

svelte
<script>
 function handleClick() {
  console.log('Clicked!')
 }
 
 function handleInput(event) {
  console.log(event.target.value)
 }
</script>
 
<!-- Inline handler -->
<button on:click={() => console.log('Clicked')}>
 Click me
</button>
 
<!-- Function handler -->
<button on:click={handleClick}>
 Click me
</button>
 
<!-- With event -->
<input on:input={handleInput} />
 
<!-- Multiple events -->
<button on:click={handleClick} on:mouseenter={() => {}}>
 Hover or click
</button>

#Event Modifiers

svelte
<!-- Prevent default -->
<form on:submit|preventDefault={handleSubmit}>
 
<!-- Stop propagation -->
<button on:click|stopPropagation={handleClick}>
 
<!-- Only once -->
<button on:click|once={handleClick}>
 
<!-- Capture phase -->
<div on:click|capture={handleClick}>
 
<!-- Chain modifiers -->
<form on:submit|preventDefault|stopPropagation={handleSubmit}>
 
<!-- Self (only if event.target is element itself) -->
<div on:click|self={handleClick}>
 
<!-- Passive (for better scroll performance) -->
<div on:wheel|passive={handleWheel}>
 
<!-- Non-passive -->
<div on:touchstart|nonpassive={handleTouch}>
 
<!-- Trusted (only if trusted event) -->
<button on:click|trusted={handleClick}>

#Bindings

#Input Bindings

svelte
<script>
 let name = ''
 let message = ''
 let checked = false
 let selected = ''
 let group = []
 let value = 5
</script>
 
<!-- Text input -->
<input bind:value={name} />
 
<!-- Textarea -->
<textarea bind:value={message}></textarea>
 
<!-- Checkbox -->
<input type="checkbox" bind:checked />
 
<!-- Radio -->
<input type="radio" bind:group={selected} value="a" />
<input type="radio" bind:group={selected} value="b" />
 
<!-- Checkbox group -->
<input type="checkbox" bind:group value="a" />
<input type="checkbox" bind:group value="b" />
 
<!-- Select -->
<select bind:value={selected}>
 <option value="a">A</option>
 <option value="b">B</option>
</select>
 
<!-- Range -->
<input type="range" bind:value min="0" max="10" />
 
<!-- Number -->
<input type="number" bind:value />
 
<!-- File -->
<input type="file" bind:files />

#Component Bindings

svelte
<!-- Child.svelte -->
<script>
 export let value
</script>
 
<input bind:value />
 
<!-- Parent.svelte -->
<script>
 let text = ''
</script>
 
<Child bind:value={text} />
<p>{text}</p>

#Element Bindings

svelte
<script>
 let div
 let input
 
 $: console.log(div) // DOM element
</script>
 
<div bind:this={div}>Content</div>
<input bind:this={input} />
 
<!-- Dimensions -->
<div bind:clientWidth={width} bind:clientHeight={height}>
 
<!-- Video/Audio -->
<video
 bind:currentTime
 bind:duration
 bind:paused
 bind:volume
></video>

#Components

#Defining Components

svelte
<!-- Button.svelte -->
<script>
 // Props (classic way)
 export let variant = 'primary'
 export let disabled = false
 
 // Svelte 5 way
 let { variant = 'primary', disabled = false } = $props()
</script>
 
<button class={variant} {disabled}>
 <slot />
</button>
 
<style>
 .primary {
  background: blue;
 }
</style>

#Using Components

svelte
<script>
 import Button from './Button.svelte'
</script>
 
<Button variant="primary">Click me</Button>
<Button variant="secondary" disabled>Disabled</Button>

#Slots

svelte
<!-- Card.svelte -->
<div class="card">
 <div class="header">
  <slot name="header" />
 </div>
 
 <div class="body">
  <slot /> <!-- Default slot -->
 </div>
 
 <div class="footer">
  <slot name="footer" />
 </div>
</div>
 
<!-- Usage -->
<Card>
 <h1 slot="header">Title</h1>
 
 <p>Content here</p>
 
 <button slot="footer">OK</button>
</Card>

#Slot Props

svelte
<!-- List.svelte -->
<script>
 export let items
</script>
 
{#each items as item}
 <slot item={item} />
{/each}
 
<!-- Usage -->
<List items={users} let:item>
 <p>{item.name}</p>
</List>

#Lifecycle

#Classic Lifecycle

svelte
<script>
 import { onMount, onDestroy, beforeUpdate, afterUpdate } from 'svelte'
 
 onMount(() => {
  console.log('Component mounted')
 
  // Return cleanup function
  return () => {
   console.log('Cleanup')
  }
 })
 
 onDestroy(() => {
  console.log('Component destroyed')
 })
 
 beforeUpdate(() => {
  console.log('Before update')
 })
 
 afterUpdate(() => {
  console.log('After update')
 })
</script>

#Svelte 5 Lifecycle

svelte
<script>
 // Use $effect instead
 $effect(() => {
  console.log('Mounted / Updated')
 
  return () => {
   console.log('Cleanup')
  }
 })
</script>

#Stores

#Writable Store

javascript
// stores.js
import { writable } from 'svelte/store'
 
export const count = writable(0)
 
export const user = writable({
 name: 'Budi',
 email: 'budi@example.com'
})

#Using Stores

svelte
<script>
 import { count } from './stores.js'
 
 // Subscribe with $
 // Auto-subscribe dan auto-unsubscribe
 $count
 
 // Update
 function increment() {
  count.update(n => n + 1)
 }
 
 // Set
 function reset() {
  count.set(0)
 }
 
 // Manual subscribe (avoid kalo bisa)
 const unsubscribe = count.subscribe(value => {
  console.log(value)
 })
 
 onDestroy(unsubscribe)
</script>
 
<p>{$count}</p>
<button on:click={increment}>+</button>

#Readable Store

javascript
import { readable } from 'svelte/store'
 
export const time = readable(new Date(), set => {
 const interval = setInterval(() => {
  set(new Date())
 }, 1000)
 
 return () => clearInterval(interval)
})

#Derived Store

javascript
import { derived } from 'svelte/store'
import { count } from './stores.js'
 
export const doubled = derived(
 count,
 $count => $count * 2
)
 
// Multiple stores
export const sum = derived(
 [count1, count2],
 ([$count1, $count2]) => $count1 + $count2
)

#Custom Stores

javascript
import { writable } from 'svelte/store'
 
function createCounter() {
 const { subscribe, set, update } = writable(0)
 
 return {
  subscribe,
  increment: () => update(n => n + 1),
  decrement: () => update(n => n - 1),
  reset: () => set(0)
 }
}
 
export const counter = createCounter()

#Transitions

#Built-in Transitions

svelte
<script>
 import { fade, fly, slide, scale } from 'svelte/transition'
 
 let visible = true
</script>
 
{#if visible}
 <div transition:fade>Fade in/out</div>
 
 <div transition:fly={{ y: 200, duration: 500 }}>
  Fly in/out
 </div>
 
 <div transition:slide>Slide in/out</div>
 
 <div transition:scale>Scale in/out</div>
{/if}
 
<!-- Separate in/out -->
<div in:fade out:slide>
 Different transitions
</div>

#Transition Parameters

svelte
<script>
 import { fly, fade } from 'svelte/transition'
</script>
 
<div
 transition:fly={{
  y: 200,
  duration: 500,
  delay: 100,
  easing: cubicOut
 }}
>
 Content
</div>
 
<div
 transition:fade={{
  duration: 300
 }}
>
 Fade
</div>

#Custom Transitions

javascript
function typewriter(node, { speed = 1 }) {
 const valid = node.childNodes.length === 1 && node.childNodes[0].nodeType === Node.TEXT_NODE
 
 if (!valid) return {}
 
 const text = node.textContent
 const duration = text.length / (speed * 0.01)
 
 return {
  duration,
  tick: t => {
   const i = Math.trunc(text.length * t)
   node.textContent = text.slice(0, i)
  }
 }
}

#Animations

svelte
<script>
 import { flip } from 'svelte/animate'
 import { quintOut } from 'svelte/easing'
 
 let items = [1, 2, 3, 4, 5]
 
 function shuffle() {
  items = items.sort(() => Math.random() - 0.5)
 }
</script>
 
<button on:click={shuffle}>Shuffle</button>
 
{#each items as item (item)}
 <div animate:flip={{ duration: 300, easing: quintOut }}>
  {item}
 </div>
{/each}

#Actions

svelte
<script>
 function clickOutside(node) {
  function handleClick(event) {
   if (!node.contains(event.target)) {
    node.dispatchEvent(new CustomEvent('outclick'))
   }
  }
 
  document.addEventListener('click', handleClick, true)
 
  return {
   destroy() {
    document.removeEventListener('click', handleClick, true)
   }
  }
 }
</script>
 
<div use:clickOutside on:outclick={() => console.log('Clicked outside')}>
 Content
</div>
 
<!-- With parameters -->
<div use:action={params}>

#SvelteKit

#Routes

plaintext
src/routes/
├── +page.svelte      # /
├── about/
│  └── +page.svelte    # /about
├── blog/
│  ├── +page.svelte    # /blog
│  └── [slug]/
│    └── +page.svelte  # /blog/[slug]
└── api/
  └── users/
    └── +server.js   # /api/users

#Load Functions

javascript
// +page.js
export async function load({ fetch, params }) {
 const response = await fetch('/api/users')
 const users = await response.json()
 
 return {
  users
 }
}
svelte
<!-- +page.svelte -->
<script>
 export let data
</script>
 
<h1>Users</h1>
{#each data.users as user}
 <p>{user.name}</p>
{/each}

#Form Actions

javascript
// +page.server.js
export const actions = {
 default: async ({ request }) => {
  const data = await request.formData()
  const email = data.get('email')
 
  // Process form
  await saveToDatabase(email)
 
  return { success: true }
 }
}
svelte
<!-- +page.svelte -->
<script>
 export let form
</script>
 
<form method="POST">
 <input name="email" type="email" />
 <button>Submit</button>
</form>
 
{#if form?.success}
 <p>Success!</p>
{/if}

#Best Practices

#Reactivity

svelte
<!-- Bad -->
<script>
 let items = []
 items.push(newItem) // Won't trigger reactivity
</script>
 
<!-- Good -->
<script>
 let items = []
 items = [...items, newItem]
</script>

#Component Props

svelte
<!-- Bad -->
<script>
 export let user
 user.name = 'Ani' // Mutating prop
</script>
 
<!-- Good -->
<script>
 export let user
 let localUser = { ...user }
 localUser.name = 'Ani'
</script>

#Keys in Lists

svelte
<!-- 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>
{/each}
 
<!-- Good - unique ID as key -->
{#each items as item (item.id)}
 <div>{item.name}</div>
{/each}

Baca Cheat Sheet Lengkap

Login atau daftar akun gratis untuk membaca cheat sheet ini.

LoginDaftar Gratis
Share: