
SvelteKit Remote Functions: Tip Güvenli Sunucu Çağrıları
SvelteKit uygulamaları geliştirirken bildik süreci hepimiz yaşadık: API için +server.ts oluştur, tipleri tanımla, fetch çağrısı yaz ve her şeyi manuel olarak bağla. SvelteKit Remote Functions tüm bunları değiştiriyor. SvelteKit 2.27’de deneysel olarak tanıtılan ve şimdi SvelteKit 3 Release Candidate‘in başlık özelliği olan remote functions, sunucu kodunuzu bileşenlerden tam uçtan uca tip güvenliği ile doğrudan çağırmanızı sağlıyor.
Bu rehberde dört fonksiyon tipinin tümünü (query, command, form ve prerender) kendi projelerinizde uygulayabileceğiniz pratik örneklerle öğreneceksiniz.
Remote Functions Nedir?
Remote functions, .remote.ts dosyalarında tanımlanan ve SvelteKit derleyicisinin otomatik olarak tipli istemci sarmalayıcılarıyla HTTP endpoint’lerine dönüştürdüğü sunucu taraflı fonksiyonlardır. Sunucu kodu yazarsınız, bir bileşende içeri aktarırsınız ve yerel bir fonksiyonmuş gibi çağırırsınız. Derleyici serializasyon, doğrulama, önbellekleme ve tip çıkarımını yönetir.
Pratikte şu şekilde görünüyor:
// src/lib/posts.remote.ts
import * as v from "valibot";
import { query } from "$app/server";
import * as db from "$lib/server/db";
export const getPost = query(v.string(), async (slug) => {
const post = await db.findPost(slug);
if (!post) error(404, "Not found");
return post;
}); <!-- src/routes/posts/[slug]/+page.svelte -->
<script>
import { getPost } from "$lib/posts.remote.js";
let { data } = $props();
const post = await getPost(data.slug);
</script>
<h1>{post.title}</h1><p>{post.content}</p> +server.ts yok, manuel fetch yok, tip tanımları yok. Derleyici her şeyi Valibot şemasından çıkarır.
Remote Functions Kurulumu
Remote functions’ı etkinleştirmek için iki deneysel bayrak yapılandırmanız gerekiyor:
// svelte.config.js
export default {
kit: {
experimental: {
remoteFunctions: true,
},
},
compilerOptions: {
experimental: {
async: true, // şablonlarda await'i etkinleştirir
},
},
}; async derleyici seçeneği, şablonlarınızda doğrudan await ifadelerini kullanmanıza olanak tanıyan ayrı bir Svelte 5 özelliğidir. Remote functions için kesinlikle gerekli olmasa da, birlikte çalışacak şekilde tasarlanmışlardır.
Dört Fonksiyon Tipi
Remote functions $app/server‘dan içeri aktarılır ve her biri belirli bir kullanım senaryosu için tasarlanmış dört çeşit olarak gelir.
1. query(): Sunucu Verisini Okuma
query() en yaygın fonksiyon tipidir. Yerleşik önbellekleme ve istek tekilleştirilmesi ile sunucudan veri çeker.
// src/lib/products.remote.ts
import * as v from "valibot";
import { query } from "$app/server";
import * as db from "$lib/server/db";
export const getProducts = query(
v.object({
category: v.string(),
limit: v.number(),
}),
async ({ category, limit }) => {
return await db.sql`
SELECT * FROM products
WHERE category = ${category}
ORDER BY created_at DESC
LIMIT ${limit}
`;
},
); <script>
import { getProducts } from "$lib/products.remote.js";
const products = await getProducts({ category: "electronics", limit: 10 });
</script>
{#each products as product}
<div>{product.name} — ${product.price}</div>
{/each} query’nin temel davranışları:
- Otomatik önbellekleme: Argümanlar önbellek anahtarı olarak serialize edilir. Nesne anahtar sırası önemli değildir,
{ limit: 10, offset: 0 }ve{ offset: 0, limit: 10 }aynı önbellek anahtarını üretir. - İstek tekilleştirilmesi: Birden fazla bileşen aynı argümanlarla aynı sorguyu tek bir render döngüsünde çağırırsa, yalnızca bir sunucu çağrısı yapılır.
- SSR gömme: SSR sırasında çekilen veriler sayfa yüküne gömülür, böylece istemci hydration sırasında ikinci bir istek yapmaz.
- Manuel yenileme: Sunucudan en son değeri yeniden çekmek için
.refresh()çağırın.
2. query.batch(): N+1 Problemini Çözme
Birden fazla bileşen bağımsız olarak ilişkili verileri sorguladığında, query.batch() eş zamanlı çağrıları tek bir sunucu isteğinde gruplar:
// src/lib/users.remote.ts
import * as v from "valibot";
import { query } from "$app/server";
export const getUser = query.batch(v.string(), async (userIds) => {
// userIds istenen tüm ID'lerin bir dizisidir
const users = await db.sql`
SELECT * FROM users WHERE id = ANY(${userIds})
`;
// Girdiden sonuca bir Map döndür
return new Map(users.map((u) => [u.id, u]));
}); On bileşen aynı makrogörevde getUser(id) çağırırsa, tüm on ID ile yalnızca bir veritabanı sorgusu çalışır.
3. query.live(): Gerçek Zamanlı Akış
Zaman içerisinde değişen veriler için query.live() asenkron üreteç kullanarak güncellemeleri aktarır:
// src/lib/notifications.remote.ts
import * as v from "valibot";
import { query } from "$app/server";
export const getNotifications = query.live(v.string(), async function* (userId) {
while (true) {
const notifications = await db.getUnread(userId);
yield notifications;
await new Promise((r) => setTimeout(r, 5000));
}
}); <script>
import { getNotifications } from "$lib/notifications.remote.js";
const notifications = await getNotifications(userId);
</script>
<span>{notifications.length} okunmamış bildiriminiz var</span> Bağlantı bileşen mount edilmiş olduğu sürece açık kalır. Birden fazla örnek tek bir bağlantı paylaşır ve SvelteKit üstel geri çekilme ile otomatik yeniden bağlanmayı yönetir.
4. command(): Zorunlu Mutasyonlar
Formlar dışındaki kullanıcı etkileşimleriyle tetiklenen mutasyonlar için command() kullanın: buton tıklama, sürükle-bırak, klavye kısayolları gibi.
// src/lib/likes.remote.ts
import * as v from "valibot";
import { command, query } from "$app/server";
export const getLikes = query(v.string(), async (postId) => {
const result = await db.sql`SELECT likes FROM posts WHERE id = ${postId}`;
return result[0].likes;
});
export const addLike = command(v.string(), async (postId) => {
await db.sql`UPDATE posts SET likes = likes + 1 WHERE id = ${postId}`;
return getLikes(postId).refresh();
}); <script>
import { getLikes, addLike } from "$lib/likes.remote.js";
let { postId } = $props();
const likes = await getLikes(postId);
</script>
<button onclick={() => addLike(postId)}>
{likes} Beğeni
</button> Önemli:
form()‘dan farklı olarak, başarılı bircommand()sorguları otomatik olarak geçersiz kılmaz. İlişkili sorgularda.refresh()çağırmalısınız veya iyimser güncellemeler için.updates()kullanmalısınız.
5. form(): Aşamalı Geliştirmeli Formlar
form(), yerleşik aşamalı geliştirme ile HTML form gönderimleri için tasarlanmıştır. JavaScript hidrate olmadan önce bile çalışır:
// src/routes/contact/contact.remote.ts
import * as v from "valibot";
import { form } from "$app/server";
import * as db from "$lib/server/db";
export const submitContact = form(
v.object({
name: v.pipe(v.string(), v.minLength(2)),
email: v.pipe(v.string(), v.email()),
message: v.pipe(v.string(), v.minLength(10)),
}),
async (data) => {
await db.insertContactMessage(data);
return { success: true };
},
); <script>
import { submitContact } from "./contact.remote.js";
</script>
<form {...submitContact.enhance()}>
<input name="name" required />
<input name="email" type="email" required />
<textarea name="message" required></textarea>
<button>Gönder</button>
</form> form’un temel davranışları:
- Aşamalı geliştirme: JavaScript olmadan standart HTML form gönderimi ile çalışır.
- Otomatik geçersiz kılma: Başarıda tüm sorgular ve load fonksiyonları otomatik olarak yenilenir.
- Zengin tip desteği:
Date,Map,SetveFilenesnelerini serialize etmek için özel bir ikili format (application/x-sveltekit-formdata) kullanır. - Alan düzeyli doğrulama: Doğrulama hataları ayrıntılı hata gösterimi için alan bazında döndürülür.
6. prerender(): Derleme Zamanlı Veri
Nadiren değişen içerikler için prerender() verileri derleme zamanında çeker ve statik varlıklar olarak sunar:
// src/lib/posts.remote.ts
import * as v from "valibot";
import { prerender } from "$app/server";
export const getPost = prerender(
v.string(),
async (slug) => {
const post = await db.findPost(slug);
if (!post) error(404, "Not found");
return post;
},
{
inputs: () => ["welcome", "about", "remote-functions"],
dynamic: true, // bilinmeyen slug'lar için çalışma zamanı geri dönüşü
},
); inputs geri çağrısı SvelteKit’e derleme zamanında hangi argüman değerlerinin oluşturulacağını söyler. dynamic: true ayarı, derleme sırasında kapsanmayan slug’lar için çalışma zamanı fetch’lerine izin verir.
Uçtan Uca Tip Güvenliği
Remote functions’ı güçlü kılan şey, tip güvenliğinin tamamen otomatik olmasıdır. İlk argüman olarak bir doğrulama şeması tanımlarsınız ve derleyici bu tipleri sunucudan istemciye otomatik olarak yayar:
// Şema sözleşmeyi tanımlar
const schema = v.object({
page: v.number(),
search: v.optional(v.string()),
});
// İşleyici doğrulanmış, tipli girdi alır
export const searchProducts = query(schema, async (input) => {
// input { page: number; search?: string } olarak tiplenmiş
return await db.search(input);
// Dönüş tipi çıkarılır ve istemcide kullanılabilir
}); İstemci tarafında, IDE’niz hem argümanlar hem de dönüş değerleri için tam otomatik tamamlama sağlar. Paylaşılan tip dosyası yok, satisfies yok, codegen adımı yok.
Bu doğrulama sadece geliştirici deneyimi için değil, aynı zamanda bir güvenlik gereksinimidir. Her remote function halka açık bir HTTP endpoint’ine derlenir, bu nedenle girdi doğrulaması hatalı veya kötü niyetli verilerin sunucu mantığınıza ulaşmasını önler.
İyimser Güncellemeler
Hem command() hem de form() .updates() ile .withOverride() kombinasyonunu kullanarak iyimser güncellemeleri destekler:
<script>
import { addLike, getLikes } from "$lib/likes.remote.js";
let { postId } = $props();
const likes = await getLikes(postId);
</script>
<button onclick={() => addLike(postId).updates(getLikes(postId).withOverride((current) => current + 1))}>
{likes} Beğeni
</button> Override anında UI’ye uygulanır. Sunucu mutasyonu başarısız olursa değer otomatik olarak geri alınır. Başarılı olursa sunucunun gerçek yanıtı override’ın yerine geçer.
Kaputun Altında Nasıl Çalışıyor
Derleme sürecini anlamak remote functions’ınızı hata ayıklamak ve optimize etmek için yardımcı olur:
- Derleme zamanı: Vite eklentisi
.remote.tsdosyalarını algılar ve her dışarı aktarılan fonksiyon için bir HTTP endpoint’i oluşturur. - Sunucu paketi: Orijinal fonksiyon olduğu gibi kalır.
- İstemci paketi: Dışarı aktarılan, oluşturulan endpoint’i çağıracak tipli bir
fetchsarmalayıcısı ile değiştirilir. - Serializasyon: Argümanlar ve dönüş değerleri
devaluekullanılarak serialize edilir.Date,Map,Set,BigIntve döngüsel referansları destekler. - SSR: Sunucu taraflı render sırasında sorgu sonuçları sayfa yükünde bir
query_responsesharitasına gömülür. İstemcide hydration sırasında yeniden fetch yapılmaz.
Remote Functions ve Alternatifler
SvelteKit 2 load + actions ile Karşılaştırma
| Özellik | load + actions | Remote Functions |
|---|---|---|
| Veri konumu | Yalnızca sayfa düzeyi | Herhangi bir bileşenden çağrılabilir |
| Tip güvenliği | Manuel veya çıkarımlı | Şema tabanlı, otomatik |
| Boilerplate | +page.server.ts + +server.ts | Tek .remote.ts dosyası |
| Aşamalı geliştirme | Manuel use:enhance | form() ile yerleşik |
| Önbellek geçersiz kılma | invalidateAll() | Otomatik (form) veya açık (command) |
| Gerçek zamanlı veri | Yerleşik değil | query.live() |
tRPC ile Karşılaştırma
| Özellik | tRPC | Remote Functions |
|---|---|---|
| Kurulum | Router + istemci + adaptör | Tek yapılandırma bayrağı |
| Framework bağlılığı | Framework bağımsız | SvelteKit’e özgü |
| Gruplama | Yerleşik | query.batch() |
| Akış | Subscriptions | query.live() |
| İyimser güncellemeler | Manuel | Yerleşik .withOverride() |
| Aşamalı geliştirme | Desteklenmiyor | form() ile yerleşik |
Performans Değerlendirmeleri
Remote functions geleneksel API desenlerine kıyasla çeşitli performans avantajları sunar:
Hydration’da istemci yeniden-fetch’i yok: SSR sorgu sonuçları sayfa yüküne serialize edilir. İstemci ikinci bir HTTP isteği yapmadan bunları yeniden kullanır ve Etkileşime Hazır Olma Süresini azaltır.
İstek tekilleştirilmesi: Birden fazla bileşen aynı sorguyu render ederse, SvelteKit yalnızca bir istek gönderir. Bu, bileşen düzeyli veri çekmede yaygın olan şelale problemini önler.
Tek-uçuş mutasyonları: Bir
form()veyacommand()işleyicisi bir sorguda.refresh()çağırdığında, yenilenmiş veri aynı HTTP yanıtında geri gelir. Ek bir gidiş-dönüş gereksizdir.Paket boyutu: API istemci kütüphanesi gerekli değildir. Oluşturulan fetch sarmalayıcıları tRPC’nin istemci paketine kıyasla minimaldir.
Statik içerik için prerender:
prerender(), dağıtımlar arasında değişmeyen içerikler için çalışma zamanı veri-çekme gecikmesini tamamen ortadan kaldırır.
Bilinmesi Gereken Kısıtlamalar
Remote functions’ı benimsemeden önce şu kısıtlamaların farkında olun:
- Deneysel: API bir bayrak arkasındadır ve değişebilir. Üretim kullanımı bu riski kabul etmeyi gerektirir.
- Sunucu gerektirir:
query,commandveform,adapter-staticile çalışmaz. Sunucu destekli bir adaptöre ihtiyacınız vardır (Node.js, Vercel, Cloudflare Workers, vb.). - Cross-origin desteği yok: Remote function endpoint’leri yalnızca aynı kaynağın (same-origin) üzerindedir. Siteler arası istekler varsayılan olarak engellenir.
- Oluşturulmuş sayfalar query kullanamaz:
export const prerender = trueolan sayfalar dinamik sorguları çağıramaz. Bunun yerineprerender()kullanın. - Resmi test hikâyesi yok: Remote functions’ın birim testi açık bir konudur. Tam SvelteKit sunucusuyla entegrasyon testi şu anda önerilen yaklaşımdır.
SvelteKit 2’den Göç
SvelteKit 2’den yükseltme yapıyorsanız, otomatik bir göç aracı mevcuttur:
npx sv@next migrate sveltekit-3 --tasks all --confirm Remote functions eklemelidir, load fonksiyonlarını veya form actions’ları zorla değiştirmez. Kademeli olarak benimseyebilirsiniz. Pratik bir göç stratejisi:
- Okuma yoğun sayfalarla başlayın:
+page.server.tsload fonksiyonlarınıquery()ile değiştirin. - Form actions’ları daha iyi tip güvenliği ve konumlama için
form()‘a taşıyın. - Form dışı mutasyonlar için
+server.tsAPI route’larınıcommand()ile değiştirin. - Çalışma zamanı verisine ihtiyaç duymayan içerik sayfaları için
prerender()kullanın.
Sonuç
SvelteKit Remote Functions, full-stack web uygulamaları oluşturma şeklimizde önemli bir değişimi temsil ediyor. Sunucu-istemci sınırını derleyiciye taşıyarak, tip güvenliğini, performansı ve geliştirici deneyimini iyileştirirken boilerplate’in tamamını ortadan kaldırıyor.
Okumalar için query(), mutasyonlar için command() ve form(), statik veri için prerender() kombinasyonu size her veri çekme deseni için eksiksiz bir araç takımı veriyor. Tümü uçtan uca tip güvenliği ve sıfır manuel bağlama ile çalışıyor.
Hâlâ deneysel olsa da, remote functions SvelteKit’in gelecek yönüdür. Şimdi öğrenmeye ve denemeye başlamak sizi kararlı sürüm için hazırlar ve daha hızlı, daha güvenli web uygulamaları oluşturmada avantaj sağlar.
Sıkça Sorulan Sorular
SvelteKit Remote Functions nedir?
Remote functions, .remote.ts dosyalarında sunucu taraflı kod yazmanızı ve bu kodu bileşenlerden doğrudan tip güvenliği ile çağırmanızı sağlayan bir SvelteKit özelliğidir. Derleyici otomatik olarak HTTP endpoint’leri ve tipli istemci sarmalayıcıları oluşturur, manuel API route’larına olan ihtiyacı ortadan kaldırır.
SvelteKit Remote Functions kararlı mı?
Remote functions SvelteKit 2.27’de deneysel olarak tanıtıldı ve SvelteKit 3 RC (Ağustos 2026) itibarıyla hâlâ deneysel bayrak arkasındadır. API değişebilir ancak temel konseptler sağlamdır ve aktif olarak geliştirilmektedir.
SvelteKit’te query ve command arasındaki fark nedir?
query() otomatik önbellekleme ve tekilleştirilmiş isteklerle sunucudan veri okumak içindir. command() buton tıklama gibi kullanıcı eylemleriyle tetiklenen mutasyonlar içindir. Temel fark, command‘ın sorguları otomatik geçersiz kılmamasıyken form()‘un kılmasıdır.
Remote Functions adapter-static ile kullanılabilir mi?
Hayır. query, form ve command, adapter-node, adapter-vercel veya adapter-cloudflare gibi sunucu destekli bir adaptör gerektirir. Yalnızca prerender() çalışma zamanı sunucusu olmadan çalışır çünkü verileri derleme zamanında çeker.
Remote Functions tRPC ile nasıl karşılaştırılır?
Remote functions SvelteKit’e özgüdür ve deneysel bayrak dışında sıfır yapılandırma gerektirir. Eşit tip güvenliği, yerleşik iyimser güncellemeler, form() ile aşamalı geliştirme ve query.live() ile akış desteği sunar. tRPC router kurulumu ve adaptör yapılandırması gerektirir.
Remote Functions gerçek zamanlı veriyi destekler mi?
Evet. query.live() asenkron üreteç alır ve değerleri istemciye aktarır. Bağlantıları otomatik yönetir, üstel geri çekilme ile yeniden bağlanır ve birden fazla bileşen örneği arasında bağlantıları paylaşır.
Remote Functions’da tip güvenliği nasıl çalışır?
İlk argüman olarak bir doğrulama şeması (Zod, Valibot veya herhangi bir Standard Schema kütüphanesi kullanarak) tanımlarsınız. Derleyici argüman ve dönüş tiplerini bu şemadan çıkarır ve istemci taraflı sarmalayıcıya yayar, sıfır manuel tip tanımıyla uçtan uca tip güvenliği sağlar.