SvelteKit'in Temel Mimarisi
SvelteKit, Svelte bileşenlerini temel alan bir uygulama çatısıdır (framework). Svelte derleyici (compiler) yaklaşımıyla çalışır: bileşenler tarayıcıya gönderilmeden önce derlenir ve çalışma zamanında (runtime) sanal DOM diff'lemesi yapan bir kütüphaneye ihtiyaç duymaz. SvelteKit bu derleyici modelinin üzerine yönlendirme (routing), veri yükleme (data loading), sunucu tarafı render (SSR) ve statik site üretimi (SSG) katmanlarını ekler.
Mimariyi anlamak için üç kavramı ayırmak gerekir:
- Svelte: Bileşen modeli ve reaktivite. Derleme zamanında çalışır.
- SvelteKit: Dosya tabanlı yönlendirme, veri yükleme, adaptörler ve render stratejileri.
- Vite: Geliştirme sunucusu ve derleme altyapısı. SvelteKit geliştirme ortamını Vite üzerinden çalıştırır.
Sürüm kapsamı: Bu rehber Svelte 5 ve SvelteKit 2 çizgisini esas alır. SvelteKit 1'den 2'ye geçişte API yüzeyi büyük ölçüde korunmuştur; ancak Svelte 5 ile gelen runes ($state, $derived, $props) reaktivite modelini değiştirdiği için eski export let ve reaktif $: ifadeleriyle yazılmış kodlar farklı davranır. Projeye başlamadan önce package.json içindeki svelte ve @sveltejs/kit sürümlerini kontrol et.
Proje Yapısı ve Yönlendirme
SvelteKit'te rotalar dosya sistemiyle tanımlanır. src/routes altındaki her klasör bir URL segmentine karşılık gelir.
src/
├── routes/
│ ├── +layout.svelte # Tüm sayfaları saran ortak düzen
│ ├── +page.svelte # "/" rotası
│ ├── +page.server.js # "/" için sunucu tarafı veri yükleme
│ └── blog/
│ ├── +page.svelte # "/blog"
│ └── [slug]/
│ ├── +page.svelte # "/blog/:slug"
│ └── +page.server.js
├── lib/ # $lib takma adıyla erişilen paylaşılan kod
└── app.html # HTML iskeleti
+ öneki taşıyan dosyalar SvelteKit'in özel dosyalarıdır ve yönlendirme ile veri yükleme davranışını belirler. Bu isimlendirme, çatının hangi dosyanın ne iş yaptığını belirsizlik olmadan bilmesini sağlar.
Dinamik Rotalar ve Parametreler
Köşeli parantezli klasör adları dinamik segmentleri tanımlar. [slug] gibi bir klasör, URL'deki o konumu yakalar ve params nesnesi üzerinden erişilebilir hale getirir.
// src/routes/blog/[slug]/+page.server.js
import { error } from '@sveltejs/kit';
import { db } from '$lib/server/db';
export async function load({ params }) {
const post = await db.getPost(params.slug);
if (!post) {
error(404, 'Yazı bulunamadı');
}
return { post };
}
load fonksiyonundan dönen nesne, aynı rotadaki +page.svelte bileşenine data prop'u olarak geçer:
<!-- src/routes/blog/[slug]/+page.svelte -->
<script>
let { data } = $props();
</script>
<article>
<h1>{data.post.title}</h1>
<div>{@html data.post.html}</div>
</article>
@html etiketi HTML'i ham olarak basar. Bu, güvenilmeyen içerikte XSS'e yol açar. Kullanıcı üretimi içeriği bu etiketle basmadan önce sunucu tarafında temizle (sanitize et); kütüphane seçimini ve sürümünü projene göre doğrula.
Veri Yükleme: Sunucu ve İstemci Ayrımı
SvelteKit'te veri yükleme iki katmanda yapılır ve bu ayrım mimarinin en kritik parçasıdır.
+page.server.js ve +layout.server.js
Bu dosyalar yalnızca sunucuda çalışır. Veritabanı bağlantıları, gizli anahtarlar ve dosya sistemi erişimi buraya aittir. +page.server.js içindeki load fonksiyonuna gelen fetch, sunucu tarafında çalışır ve göreli URL'leri çözebilir. Bu dosyalardan dönen veri, istemciye serileştirilerek gönderilir.
Kritik nokta: +page.server.js içinden döndürdüğün her şey istemciye ulaşır. API anahtarı, oturum tokeni veya iç kullanıcı verisi döndürme.
+page.js ve +layout.js
Bu dosyalar hem sunucuda hem istemcide çalışabilir. Evrensel (universal) load fonksiyonları, SSR sırasında sunucuda, istemci tarafı gezinmede (client-side navigation) tarayıcıda çalışır. Bu yüzden içlerinde tarayıcıya özel API'lere (window, localStorage) doğrudan erişemezsin. Bunun yerine browser bayrağını veya onMount gibi yaşam döngüsü kancalarını kullan.
// src/routes/dashboard/+page.js
import { browser } from '$app/environment';
export async function load({ fetch }) {
const res = await fetch('/api/stats');
const stats = await res.json();
return {
stats,
tema: browser ? localStorage.getItem('tema') : 'acik'
};
}
Bu ayrım, güvenlik sınırını netleştirir. Gizli veri sunucu load fonksiyonunda kalır; paylaşılan mantık evrensel load fonksiyonunda durur.
Render Stratejileri ve Adaptörler
SvelteKit, aynı kod tabanından farklı dağıtım hedefleri üretebilir. Bunu adapter kavramı sağlar.
adapter-node: Node.js sunucusu olarak çalışır. SSR ve dinamik rotalar için uygundur.adapter-static: Tamamen statik dosyalar üretir. İçerik ağırlıklı siteler için uygundur; dinamik sunucu mantığı çalışmaz.- Platform adaptörleri: Belirli barındırma ortamlarına özel çıktı üretir.
Render davranışı sayfa veya düzen düzeyinde prerender, ssr ve csr seçenekleriyle ayarlanır:
// src/routes/hakkinda/+page.js
export const prerender = true;
prerender = true bu rotayı derleme zamanında statik HTML'e dönüştürür. ssr = false ise sayfayı yalnızca istemcide render eder; bu, SEO'yu ve ilk yükleme performansını olumsuz etkiler, bu yüzden yalnızca gerçekten gerekli olduğunda kullan.
Adaptör seçimi, mimari kararların çoğunu belirler. adapter-static seçtiğinde sunucu tarafı load fonksiyonları ve form action'ları devre dışı kalır. Bu yüzden adaptörü projenin başında, ihtiyaçları netleştirdikten sonra seç.
Form Actions ve Mutasyonlar
Veri okuma load ile yapılır; veri yazma için SvelteKit form action'ları sunar. Bu, ayrı bir API katmanı yazmadan sunucu tarafı mutasyonları yönetmenin yoludur.
// src/routes/gonderi/+page.server.js
import { fail, redirect } from '@sveltejs/kit';
import { db } from '$lib/server/db';
export const actions = {
varsayilan: async ({ request, locals }) => {
const data = await request.formData();
const baslik = data.get('baslik');
if (!baslik || baslik.length < 3) {
return fail(400, { baslik, hata: 'Başlık en az 3 karakter olmalı' });
}
if (!locals.kullanici) {
return fail(401, { hata: 'Yetkisiz istek' });
}
const id = await db.createPost({ baslik, yazar: locals.kullanici.id });
redirect(303, `/gonderi/${id}`);
}
};
Action'lar yalnızca sunucuda çalışır ve locals üzerinden istek bağlamına erişir. locals nesnesini hooks.server.js içinde doldurursun; oturum doğrulaması tipik olarak burada yapılır.
// src/hooks.server.js
export async function handle({ event, resolve }) {
const oturum = event.cookies.get('oturum');
if (oturum) {
event.locals.kullanici = await dogrulaOturum(oturum);
}
return resolve(event);
}
handle kancası her isteği keser. Kimlik doğrulama, loglama ve yanıt başlıklarını burada yönetirsin. Bu kancayı ağır işler için kullanma; her istekte çalıştığı için gecikmeyi doğrudan etkiler.
Avantajlar ve Ödünleşimler
SvelteKit'in pratikte öne çıkan avantajları:
- Derleme zamanı reaktivite: Sanal DOM yok. Üretilen JavaScript, bileşenin gerçek DOM güncellemelerini doğrudan hedefler. Bu, çalışma zamanı yükünü azaltır.
- Tek kod tabanı, çoklu render stratejisi: Aynı projede SSR, SSG ve CSR sayfaları bir arada kullanılabilir.
- Dosya tabanlı yönlendirme ve veri yükleme: Rota tanımı ile veri yükleme aynı yerde durur; ayrı bir yönlendirme yapılandırması gerekmez.
- Form action'ları: Basit mutasyonlar için ayrı API uçları yazma ihtiyacını azaltır.
- Vite entegrasyonu: Hızlı geliştirme sunucusu ve HMR.
Ödünleşimler:
- Derleyici bağımlılığı: Svelte kodu standart JavaScript değildir; derlenmesi gerekir. Bu, bazı araç zincirlerinde esneklik kaybı demektir.
- Ekosistem büyüklüğü: React veya Vue ekosistemine kıyasla hazır bileşen ve kütüphane sayısı daha azdır.
- Adaptör kararları geri dönüşü zor: Statik adaptörden Node adaptörüne geçmek, sunucu mantığının yeniden yazılmasını gerektirebilir.
- Svelte 5 runes geçişi: Eski reaktivite modeline alışkın ekipler için öğrenme eğrisi vardır.
Yaygın Hatalar
Sunucu load fonksiyonunda sır sızdırma. +page.server.js içinden dönen her alan istemciye gider. Dönen nesneyi bilinçli olarak daralt.
Evrensel load içinde tarayıcı API'si kullanma. window veya localStorage SSR sırasında tanımsızdır ve sunucu hatası verir. browser bayrağıyla koşullandır.
ssr = false'ı varsayılan yapma. SEO ve ilk boyama performansı düşer. Yalnızca tarayıcıya özel bağımlılığı olan sayfalarda kullan.
handle kancasında ağır iş yapma. Her istekte çalıştığı için veritabanı sorgusu gibi işlemleri buraya taşımak gecikmeyi artırır.
@html ile ham kullanıcı içeriği basma. XSS riski. İçeriği sunucu tarafında temizle.
Adaptörü sonradan değiştirme. Render stratejisi ile adaptör birbirine bağlıdır; kararı erken ver.
Güvenlik Notları
- Sunucu
loadfonksiyonlarının döndürdüğü veri, istemciye serileştirilir. Hassas alanları döndürme. - Form action'larında yetki kontrolünü
localsüzerinden yap; istemciden gelen verilere güvenme. - CSRF koruması: SvelteKit, form action'lar için
originkontrolü yapar; ancak kendi API uçlarını yazıyorsan bu korumayı ayrıca ele alman gerekir. - Çerez ayarlarında
httpOnly,securevesameSitebayraklarını projenin dağıtım ortamına göre yapılandır. handlekancasında eklediğin güvenlik başlıkları (CSP, HSTS) tüm yanıtları kapsar; bunları merkezi tut.
Sonuç
SvelteKit'in mimarisi, derleme zamanı reaktivite ile sunucu-istemci veri yükleme ayrımı üzerine kuruludur. Bu ayrımı doğru kullanmak, hem güvenlik hem performans açısından belirleyicidir. Sunucu load fonksiyonlarını gizli veri ve veritabanı erişimi için, evrensel load fonksiyonlarını paylaşılan mantık için, form action'ları da mutasyonlar için kullan. Adaptör ve render stratejisi kararını projenin başında ver; bu kararlar geri dönüşü en zor olanlardır.