Episode ini membahas alur data di SvelteKit: load functions di server dan client, fetching data memakai fetch di dalam load, form handling dengan server actions dan progressive enhancement, serta penanganan error dan redirect. Kalian akan memahami bagaimana data mengalir dari server ke komponen.

Halaman statis hanya awal. Aplikasi nyata membutuhkan data: daftar artikel, detail pengguna, atau hasil pencarian. Episode 5 membahas dua mekanisme inti SvelteKit yang menggerakkan data: load functions untuk mengambil data sebelum render, dan server actions untuk memproses input dari form.
Keduanya dirancang untuk satu pengalaman: satu model mental yang sama baik di server maupun client. Load function yang sama bisa berjalan saat SSR untuk memberikan HTML cepat, lalu berjalan lagi di client untuk navigasi berikutnya yang instan.
Di akhir episode ini kalian bisa membangun halaman yang mengambil data dinamis dan memproses input pengguna dengan aman, tanpa perlu menulis endpoint API secara manual untuk setiap kasus.
File +page.server.js berisi load function yang hanya berjalan di server. Ini tempat yang tepat untuk mengakses database, membaca secret, atau melakukan redirect sebelum halaman dirender.
export const load = async (event) => {
const { params, locals } = event;
const artikel = await cariArtikel(params.slug);
if (!artikel) {
throw redirect(303, "/artikel");
}
return { artikel };
};Data yang dikembalikan diserialisasi dan dikirim ke client. Nilai yang tidak bisa diserialisasi, seperti instance class atau fungsi, tidak akan sampai ke browser.
File +page.js (tanpa .server) berjalan di server saat SSR dan di client saat navigasi. Cocok untuk data publik yang boleh diambil dari browser.
export const load = async ({ fetch }) => {
const res = await fetch("/api/artikel");
const daftar = await res.json();
return { daftar };
};Selama SSR, fetch bawaan di load function berjalan di server dan mengikuti cookie request asli. Di client, fetch yang sama berjalan normal. Ini membuat kode identik di kedua sisi.
Fungsi fetch yang tersedia sebagai argumen load lebih pintar daripada fetch global: ia meneruskan cookie, berjalan di server saat SSR, dan mendeteksi request internal ke route sendiri sehingga tidak menambah beban jaringan.
Gunakan event.fetch ketika kalian ingin memanggil endpoint +server.js milik aplikasi, atau mengambil data dari API eksternal dengan header yang sama. Hasilnya bisa di-cache dan di-streaming bersama halaman.
Aturan praktisnya:
+page.server.js.+page.js.src/lib dan panggil dari kedua sisi.Untuk mencegah data sensitif bocor, jangan pernah memuat secret di universal load — kode +page.js dikirim ke browser dan bisa dibaca siapa pun.
SvelteKit menawarkan server actions: fungsi di +page.server.js yang menangani submit form. Form dikirim sebagai POST, dan hasilnya membuat state di client diperbarui tanpa reload penuh.
export const actions = {
login: async ({ request }) => {
const form = await request.formData();
const email = String(form.get("email") ?? "");
const password = String(form.get("password") ?? "");
if (!email || !password) {
return { error: "Email dan password wajib diisi" };
}
return { success: true };
}
};Di komponen, arahkan form ke action dengan atribut action yang berisi tanda tanya diikuti nama action, lalu tambahkan directive use:enhance untuk progressive enhancement.
<script>
import { enhance } from "$app/forms";
let { form } = $props();
</script>
<form method="POST" action="?/login" use:enhance>
<input name="email" type="email" placeholder="Email" />
<input name="password" type="password" placeholder="Password" />
<button type="submit">Masuk</button>
</form>
{#if form?.error}
<p class="error">{form.error}</p>
{/if}Dengan use:enhance, submit dikirim lewat fetch: form tidak kehilangan state, animasi bisa ditambahkan, dan hasil action langsung tersedia. Tanpa JavaScript, form tetap bekerja karena jatuh ke mekanisme POST native — inilah esensi progressive enhancement.
Untuk memindahkan pengguna di dalam load atau action, lemparkan redirect:
import { redirect } from "@sveltejs/kit";
export const actions = {
logout: async (event) => {
event.cookies.delete("session", { path: "/" });
throw redirect(303, "/login");
}
};Gunakan kode status 303 setelah POST (PRG pattern), 301 untuk redirect permanen, dan 307 saat method harus dipertahankan. throw redirect(303, "/login") selalu menghentikan eksekusi fungsi.
Untuk situasi yang benar-benar gagal, gunakan helper error dari @sveltejs/kit:
import { error } from "@sveltejs/kit";
export const load = async ({ params }) => {
const artikel = await cariArtikel(params.slug);
if (!artikel) {
throw error(404, "Artikel tidak ditemukan");
}
return { artikel };
};Error yang dilempar dirender oleh +error.svelte di tingkat layout terdekat. Kalian bisa menampilkan pesan yang ramah, kode status, dan tombol kembali — jauh lebih baik daripada halaman error bawaan browser.
Inti yang harus dibawa pulang:
+page.server.js hanya di server, +page.js juga berjalan di client.event.fetch di load meneruskan cookies, berjalan di server saat SSR, dan efisien untuk request internal.+page.server.js menangani submit form tanpa perlu endpoint manual.use:enhance memberi progressive enhancement; tanpa JavaScript form tetap bekerja.throw redirect menghentikan eksekusi dan memindahkan pengguna; throw error menampilkan halaman error terstruktur.+page.js dikirim ke browser, jadi jangan pernah meletakkan secret di sana.Di episode 6 selanjutnya kita bergeser ke sisi presentasi: reactive UI & components. Kalian akan mempelajari Svelte component basics, reactive statements dan bindings, slot serta context module, dan styling scoped dengan CSS.