Web Dev 25 Sep 2026 70 views 0 komentar

SvelteKit untuk Pemula - Bikin Web App Cepat dengan SSR dan Svelte 5 dari Nol

SvelteKit untuk Pemula - Bikin Web App Cepat dengan SSR dan Svelte 5 dari Nol

Beberapa bulan lalu saya bikin landing page pakai Next.js, dan jujur, performanya oke tapi bundle size-nya bikin gerah. Halaman sederhana aja ngirim 200KB JavaScript ke browser. Terus saya denger tentang SvelteKit dari teman, katanya "kamu harus coba, bundle-nya kecil banget". Saya coba, dan ya, halaman yang sama cuma butuh 30KB JS. Beda jauh.

Kalau kamu lagi cari framework yang cepat, ringan, dan gak bikin browser pusing, SvelteKit jawabannya. Framework ini pakai Svelte 5 (versi terbaru dengan runes mode) yang compile ke vanilla JavaScript bukan virtual DOM kayak React atau Vue. Hasilnya? Aplikasi yang load cepat dan interaktif tanpa overhead runtime.

Dalam tutorial ini, saya mau ajak kamu bikin web app sederhana dari nol pakai SvelteKit. Kita bikin aplikasi todo list dengan SSR (Server-Side Rendering), form handling, dan API route. Gak perlu pengalaman Svelte sebelumnya saya jelasin step by step.

Apa itu SvelteKit dan Kenapa Harus Pakai?

SvelteKit itu meta-framework untuk Svelte, sama kayak Next.js untuk React atau Nuxt untuk Vue. Tapi bedanya, Svelte gak pakai virtual DOM. Setiap komponen di-compile jadi JavaScript murni yang langsung manipulasi DOM. Artinya, gak ada diffing overhead di runtime.

Beberapa keunggulan SvelteKit:

  • Bundle size kecil: Karena compiler ngelakuin optimisasi saat build, hasil akhirnya jauh lebih kecil dari React/Vue
  • SSR otomatis: Setiap page langsung server-rendered di first load, jadi SEO-friendly dan cepat
  • File-based routing: Bikin file di src/routes, jadi route. Gak perlu konfigurasi router manual
  • Universal load function: Code yang jalan di server DAN client, gak perlu bikin terpisah
  • Adapter system: Deploy ke Vercel, Netlify, VPS, atau static hosting tinggal ganti adapter

Svelte 5 yang terbaru juga ngenalin runes sistem reaktivitas baru yang lebih eksplisit dan gampang di-debug dibanding let reactive di Svelte 4. Kalau kamu pernah pakai React hooks, konsepnya mirip tapi syntax-nya lebih bersih.

Persiapan: Install Node.js dan Bikin Project

Pastikan kamu punya Node.js versi 18 atau lebih baru. Cek dengan:


node --version
# v20.11.0 atau lebih baru oke

Kalau belum install, download dari nodejs.org atau pakai nvm:


# Install nvm
curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.7/install.sh | bash

# Install Node 20 LTS
nvm install 20
nvm use 20

Sekarang bikin project SvelteKit. Buka terminal, lalu:


npx sv create my-svelte-app

Command ini bakal nanya beberapa hal:

  • Template: Pilih "SvelteKit minimal" (atau "Demo" kalau mau liat contoh)
  • Type checking: Pilih "TypeScript" (saran: pakai, biar gampang debug)
  • Additional options: Pilih "Add Playwright for browser testing" kalau mau, tapi gak wajib

Setelah selesai, masuk ke folder dan install dependencies:


cd my-svelte-app
npm install
npm run dev -- --open

Browser otomatis buka http://localhost:5173. Kamu bakal liat halaman welcome SvelteKit. Selamat, project pertama kamu udah jalan!

Memahami Struktur Folder SvelteKit

Sebelum kita mulai coding, pahami dulu struktur project-nya:


my-svelte-app/
|-- src/
| |-- routes/
| | |-- +page.svelte # Halaman homepage (UI)
| | |-- +page.ts # Load function (optional)
| | |-- +layout.svelte # Layout wrapper (navbar, footer)
| | |-- about/
| | |-- +page.svelte # Halaman /about
| |-- app.html # Template HTML root
| |-- app.css # CSS global
|-- static/
| |-- favicon.png # Static assets
|-- svelte.config.js # Konfigurasi SvelteKit
|-- vite.config.ts # Konfigurasi Vite
|-- package.json

Intinya: setiap folder di src/routes jadi satu route. File +page.svelte adalah komponen halaman, +page.ts (atau +page.server.ts) untuk load function, dan +layout.svelte untuk layout yang dipakai semua page.

Yang penting diingat: file yang diawali + itu "special" SvelteKit otomatis recognize. File tanpa + gak dianggap route, jadi aman untuk bikin komponen helper.

Membangun Aplikasi Todo List dengan Svelte 5 Runes

Sekarang kita bikin aplikasi todo list yang berfungsi. Kita mulai dari struktur route dan komponennya.

Pertama, bikin file store untuk manage state todo. Bikin file src/lib/stores.svelte.ts:


// src/lib/stores.svelte.ts
// Svelte 5 runes mode - pakai $state() untuk reactive state

interface Todo {
 id: number;
 text: string;
 done: boolean;
}

class TodoStore {
 items = $state<Todo[]>([]);
 filter = $state<'all' | 'active' | 'done'>('all');

 add(text: string) {
 if (!text.trim()) return;
 this.items = [
 ...this.items,
 { id: Date.now(), text: text.trim(), done: false }
 ];
 }

 toggle(id: number) {
 this.items = this.items.map(t =>
 t.id === id ? { ...t, done: !t.done } : t
 );
 }

 remove(id: number) {
 this.items = this.items.filter(t => t.id !== id);
 }

 get filtered() {
 if (this.filter === 'active') return this.items.filter(t => !t.done);
 if (this.filter === 'done') return this.items.filter(t => t.done);
 return this.items;
 }

 get remaining() {
 return this.items.filter(t => !t.done).length;
 }
}

export const todos = new TodoStore();

Di Svelte 5, $state() itu rune untuk bikin reactive state. Kalau kamu pernah pakai React useState, konsepnya mirip tapi gak perlu hooks atau dependency array. Cukup assign value baru dan UI auto-update.

Sekarang bikin komponen utama di src/routes/+page.svelte:


<script lang="ts">
 import { todos } from '$lib/stores.svelte';
 let input = $state('');

 function handleSubmit(e: Event) {
 e.preventDefault();
 todos.add(input);
 input = '';
 }
</script>

<main>
 <h1>Todo List</h1>
 <p class="subtitle">Bikin dengan SvelteKit + Svelte 5 Runes</p>

 <form on:submit={handleSubmit}>
 <input
 type="text"
 bind:value={input}
 placeholder="Mau ngapain hari ini?"
 />
 <button type="submit">Tambah</button>
 </form>

 <div class="filters">
 <button class:active={todos.filter === 'all'}
 onclick={() => todos.filter = 'all'}>Semua</button>
 <button class:active={todos.filter === 'active'}
 onclick={() => todos.filter = 'active'}>Aktif</button>
 <button class:active={todos.filter === 'done'}
 onclick={() => todos.filter = 'done'}>Selesai</button>
 </div>

 <ul>
 {#each todos.filtered as todo (todo.id)}
 <li class:done={todo.done}>
 <input type="checkbox" checked={todo.done}
 onchange={() => todos.toggle(todo.id)} />
 <span>{todo.text}</span>
 <button onclick={() => todos.remove(todo.id)}>Hapus</button>
 </li>
 {/each}
 </ul>

 <p class="count">{todos.remaining} dari {todos.items.length} belum selesai</p>
</main>

<style>
 main { max-width: 500px; margin: 0 auto; padding: 2rem; }
 form { display: flex; gap: 0.5rem; margin-bottom: 1rem; }
 input[type="text"] {
 flex: 1; padding: 0.75rem; border: 1px solid #ccc;
 border-radius: 4px; font-size: 1rem;
 }
 button {
 padding: 0.75rem 1.5rem; background: #ff3e00; color: white;
 border: none; border-radius: 4px; cursor: pointer;
 }
 .filters { display: flex; gap: 0.5rem; margin-bottom: 1rem; }
 .filters button {
 background: transparent; color: #333;
 border: 1px solid #ddd; font-size: 0.85rem;
 }
 .filters button.active {
 background: #ff3e00; color: white; border-color: #ff3e00;
 }
 ul { list-style: none; padding: 0; }
 li {
 display: flex; align-items: center; gap: 0.75rem;
 padding: 0.75rem; border-bottom: 1px solid #eee;
 }
 li.done span { text-decoration: line-through; color: #999; }
 li button {
 background: #e74c3c; font-size: 0.75rem; padding: 0.3rem 0.6rem;
 }
 .count { color: #666; font-size: 0.9rem; margin-top: 1rem; }
</style>

Beberapa hal yang perlu kamu perhatiin di kode di atas:

  • bind:value={input} two-way binding, sama kayak v-model di Vue atau onChange + value di React. Tapi lebih ringkas.
  • {#each ... as ... (key)} Svelte's each block, key di akhir untuk efisiensi update
  • class:done={todo.done} class binding, nambah class done kalau todo.done true
  • on:submit dan onclick event listener (Svelte 5 pakai onclick tanpa on: prefix untuk DOM events)

Server-Side Rendering dan Load Function

Salah satu kekuatan SvelteKit itu SSR. Default-nya, setiap page di-render di server dulu sebelum dikirim ke browser. Ini bikin halaman cepat dan SEO-friendly.

Tapi bagaimana kalau kita mau ambil data dari API atau database sebelum render? Pakai load function. Bikin file src/routes/+page.ts (atau +page.server.ts kalau code cuma boleh jalan di server):


// src/routes/+page.server.ts
import type { PageServerLoad } from './$types';

export const load: PageServerLoad = async ({ fetch }) => {
 // fetch di sini jalan di server saat SSR
 // lalu di-client saat client-side navigation
 const res = await fetch('/api/todos');
 const todos = await res.json();

 return {
 todos: todos
 };
};

Di +page.svelte, kamu akses datanya lewat data prop:


<script lang="ts">
 let { data } = $props();
 // data.todos berisi hasil dari load function
</script>

{#each data.todos as todo (todo.id)}
 <div>{todo.text}</div>
{/each}

Yang keren: load function ini universal. Saat first load (SSR), jalan di server. Saat client-side navigation (SPA mode), jalan di browser. Kamu gak perlu nulis dua versi code. SvelteKit handle semuanya.

Bikin API Route di SvelteKit

SvelteKit juga bisa jadi backend API. Bikin endpoint itu sama kayak bikin page tinggal bikin file +server.ts di folder route:


// src/routes/api/todos/+server.ts
import { json } from '@sveltejs/kit';
import type { RequestHandler } from './$types';

// Mock data (di production, pakai database sungguhan)
let todos = [
 { id: 1, text: 'Belajar SvelteKit', done: false },
 { id: 2, text: 'Deploy ke Vercel', done: false }
];

export const GET: RequestHandler = async () => {
 return json(todos);
};

export const POST: RequestHandler = async ({ request }) => {
 const body = await request.json();
 const newTodo = {
 id: Date.now(),
 text: body.text,
 done: false
 };
 todos = [...todos, newTodo];
 return json(newTodo, { status: 201 });
};

export const DELETE: RequestHandler = async ({ url }) => {
 const id = Number(url.searchParams.get('id'));
 todos = todos.filter(t => t.id !== id);
 return json({ success: true });
};

Kalau kamu butuh database real, tinggal install Prisma atau Drizzle ORM, connect ke PostgreSQL atau MySQL, dan query di dalam +server.ts. Sama kayak bikin API di Express atau Fastify, tapi tanpa setup tambahan.

Deploy SvelteKit ke VPS atau Vercel

SvelteKit pakai sistem adapter untuk build. Default adapter bikin app yang jalan di Vercel atau Netlify. Tapi kalau kamu deploy ke VPS sendiri, pakai @sveltejs/adapter-node:


npm install -D @sveltejs/adapter-node

Edit svelte.config.js:


import adapter from '@sveltejs/adapter-node';
import { vitePreprocess } from '@sveltejs/vite-plugin-svelte';

export default {
 preprocess: vitePreprocess(),
 kit: {
 adapter: adapter({
 // Port default 3000
 envPrefix: 'PUBLIC_'
 })
 }
};

Build dan jalankan:


npm run build
node build/index.js

# App jalan di port 3000
# Bisa pakai PM2 untuk production:
npm install -g pm2
pm2 start build/index.js --name svelte-app
pm2 save
pm2 startup

Untuk production di VPS, pakai nginx sebagai reverse proxy di depannya:


server {
 listen 80;
 server_name myapp.example.com;

 location / {
 proxy_pass http://localhost:3000;
 proxy_http_version 1.1;
 proxy_set_header Host $host;
 proxy_set_header X-Real-IP $remote_addr;
 proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
 proxy_set_header X-Forwarded-Proto $scheme;
 }
}

Atau kalau mau yang paling gampang, deploy ke Vercel: npx vercel. Tinggal push ke GitHub, connect repo, dan auto-deploy setiap push. SvelteKit punya adapter Vercel built-in.

Tips dan Best Practices SvelteKit

Setelah bikin beberapa project dengan SvelteKit, ini hal-hal yang saya pelajari:

  • Pakai $state di class, bukan global variable. Kalau kamu bikin store global, pakai class dengan $state() di field-nya. Lebih predictable dan gampang di-test.
  • Jangan lupa key di {#each}. Tanpa key, Svelte gak tau elemen mana yang berubah, jadi mungkin render ulang semua. Tambahkan (item.id) di akhir each block.
  • Pisah logic ke +page.server.ts kalau sensitif. Code di file +page.svelte terkirim ke browser. Code di +page.server.ts cuma jalan di server. Taruh API key dan database query di sana.
  • Pakai export const prerender = true untuk static pages. Halaman About, Privacy, dan blog posts bisa di-prerender jadi HTML statis. Lebih cepat dan murah untuk hosting.
  • Test performa dengan Lighthouse. SvelteKit sering dapet 95+ di semua kategori Lighthouse tanpa effort tambahan.

SvelteKit vs Next.js vs Nuxt: Mana yang Pilih?

Tabel singkat buat bantu kamu putuskan:

  • SvelteKit: Bundle paling kecil, syntax paling bersih, cocok untuk project baru yang mau performa maksimal. Kurva belajar paling landai.
  • Next.js: Ekosistem terbesar, App Router powerful, cocok kalau tim sudah familiar React. Tapi bundle size besar dan konsep server/client component bisa bikin pusing.
  • Nuxt: Kalo tim Vue, ini no-brainer. Auto-imports dan file routing oke. Tapi performa gak secepat Svelte.

Kalau kamu baru mulai project dan bebas pilih stack, saya saranin coba SvelteKit. Developer experience-nya enak banget. Gak perlu pusing useEffect dependency array atau memo yang gak efektif. Cukup tulis kode, dan biarin compiler optimisasi.

Kesimpulan

SvelteKit itu framework yang nge-rasa "benar" buat bikin web app. Compiler approach-nya bikin bundle kecil, runes mode di Svelte 5 bikin reaktivitas gampang dipahami, dan file-based routing bikin struktur project bersih. Untuk developer Indonesia yang lagi cari alternatif selain Next.js, SvelteKit worth banget dicoba.

Kalau kamu udah pernah pakai SvelteKit, atau ada bagian tutorial ini yang mau kamu tanya, komen di bawah ya. Saya mau denger pengalaman kalian terutama kalau ada yang udah deploy production dan mau share tips-nya.


Bagikan artikel ini:

Komentar (0)

Belum ada komentar. Jadilah yang pertama memberikan tanggapan!

Tinggalkan Komentar