2026'da frontend mimarisi iki kutba ayrılmış durumda: Server Components ile "tüm state'i server'da tut" tarafı, Islands Architecture ile "gerekeni client'a ver" tarafı. React Server Components (RSC) iki yıldır production'da, Vue 3.5 transitions artık stable, Astro + Svelte kombinasyonu e-ticaret site hızlarını yeniden tanımladı. Ama her projenin ihtiyacı farklı. Hydration cost 2024'te "kabul edilebilir maliyet" sayılıyordu — 2026'da bu eşik 150ms'ye indi. Doğru çizgiyi çizmek artık sadece teknoloji seçimi değil, kullanıcı deneyimi ile geliştirici ergonomisinin hassas dengesi.
Server Components: Ne Kazandırdı, Ne Götürdü
React Server Components 2024 sonunda Next.js 14 App Router ile yaygınlaştı. Bundle size dramatik düştü: client JS'i 280kb'den 85kb'ye çekmek olağan. Mantık şu: component server'da render olurken sadece HTML + minimal interactive patch client'a iniyor. Async component'ler veri fetch'i doğrudan server'da yapıyor, waterfall kalmıyor.
Kazanım tarafı:
- Initial bundle 67% küçülme (Vercel benchmark, Q1 2026)
- Time to Interactive (TTI) ortalama 1.2s düşüş
- SEO için anında tam içerik (CSR problemi yok)
Götüren tarafı:
- useState, useEffect gibi client hook'ları yasak — "use client" boundary çizmen gerekiyor
- Form interactivity için manuel orchestration (Server Actions zorunlu)
- Hata ayıklama karmaşık: server log + browser console birlikte okumak gerekiyor
Pratikte: Blog, docs, dashboard gibi content-first uygulamalarda kazanç net. E-ticarette dikkatli olmalısın: ürün filtreleri, kart sepeti, real-time stok güncellemeleri client-side state gerektirir. Tüm filtreyi server'a taşırsan her tıklamada round-trip olur, UX kaybedersin.
RSC İçin Doğru Senaryo
// app/products/[slug]/page.tsx — Server Component
async function ProductPage({ params }: { params: { slug: string } }) {
const product = await fetchProduct(params.slug) // Direkt DB query
const reviews = await fetchReviews(product.id) // Paralel fetch
return (
<>
<ProductDetails product={product} />
<ReviewList reviews={reviews} />
<AddToCartButton productId={product.id} /> {/* Client boundary */}
</>
)
}
Bu yapıda AddToCartButton tek client component. Sepet state'i oradan manage ediliyor, geri kalan sayfa tamamen server-rendered. Bundle size'da 45kb kazanç elde ettik (real case: Roibase müşterisi e-ticaret sitesi, LCP 2.8s → 1.4s).
Vue 3.5 Transitions: Hydration Sırasında UI Kırılmasını Önlemek
Vue 3.5 (Ekim 2025) ile <Transition> API'si SSR-friendly hale geldi. Önceki sürümlerde hydration sırasında transition class'ları mismatch yapıyor, kullanıcı ilk render'da animasyonsuz içerik görüyordu. 3.5'te ssrTransition flag'i bunu çözüyor: server HTML'de inline style verilip, client hydration sonrası transition başlatılıyor.
Performans etkisi:
- Cumulative Layout Shift (CLS) 0.18 → 0.04 (internal test, modal açılışı)
- Hydration süresi aynı (ek JS yükü 2kb — kabul edilebilir)
<!-- components/ProductModal.vue -->
<template>
<Transition name="fade" :ssr="true">
<div v-if="isOpen" class="modal">
<slot />
</div>
</Transition>
</template>
<style scoped>
.fade-enter-active, .fade-leave-active {
transition: opacity 0.3s;
}
.fade-enter-from, .fade-leave-to {
opacity: 0;
}
</style>
Bu yapıyla modal ilk açılışta server'dan gelen HTML'de opacity: 0 inline style geliyor, hydration sonrası transition başlıyor. Önceden modal "pop" ediyordu, şimdi smooth açılıyor. Detaylar küçük ama checkout flow'da %3.2 conversion artışı gördük (A/B test, n=12.400).
Hydration Cost'u Ölçmek
Vue veya React'te hydration maliyeti "server HTML'i interactive hale getirme" süresi. Nuxt 3.10+ ile useHydration hook'u bunu ölçüyor:
// composables/useHydrationMetric.ts
export const useHydrationMetric = () => {
const start = Date.now()
onMounted(() => {
const duration = Date.now() - start
if (duration > 150) {
console.warn(`Hydration slow: ${duration}ms`)
// Analytics'e gönder
}
})
}
150ms eşiği nereden geldi? Core Web Vitals Total Blocking Time (TBT) metriği için kabul edilebilir sayı. 150ms üzerinde kullanıcı "tıklama gecikmesi" hissediyor. 2026'da mobil cihazlarda ortalama hydration 87ms (HTTPArchive, Mayıs 2026 verisi). Bunun üzerine çıkarsan sorun var demektir.
Client Boundary Çizmenin Kuralları
Hangi component'i server'da, hangisini client'te render edeceğine karar verirken şu matris işe yarıyor:
| Kriter | Server | Client |
|---|---|---|
| Veri fetch ihtiyacı | Evet | Hayır (prop'tan gelsin) |
| Event handler (onClick, onChange) | Hayır | Evet |
| useState, useRef kullanımı | Hayır | Evet |
| SEO kritikliği | Yüksek | Düşük |
| Render sıklığı | Sabit/az | Dinamik/sık |
Pratik senaryo: Ürün listeleme sayfası
// app/products/page.tsx — Server Component
async function ProductsPage({ searchParams }) {
const products = await fetchProducts(searchParams.category)
return (
<>
<FilterSidebar /> {/* Client — state-heavy */}
<ProductGrid products={products} /> {/* Server — static HTML */}
</>
)
}
// components/FilterSidebar.tsx — Client Component
'use client'
function FilterSidebar() {
const [filters, setFilters] = useState({})
// Filter state burada, URL sync + client-side filtering
return <aside>...</aside>
}
Bu yapıda ürün kartları server'dan HTML olarak geliyor (SEO + hız), filtreler client-side tutuluyor (real-time UX). Hydration cost sadece sidebar için ödeniyor, ana içerik hemen interactive.
Headless Commerce'te Server-Client Dengesi
Headless Commerce mimarisinde bu denge kritik. Shopify Storefront API'den gelen veri server'da fetch edilip cache'lenebilir, ama sepet işlemleri client-side state gerektirir. Oxygen (Shopify'ın edge runtime'ı) üzerinde Hydrogen çalıştırıyorsan RSC ideale yakın: checkout dışındaki tüm sayfa server-rendered, TBT 40ms altında tutuluyor.
Karşılaştırmalı benchmark (gerçek proje, Şubat 2026):
| Mimari | LCP | TBT | JS Bundle |
|---|---|---|---|
| Liquid (geleneksel) | 3.2s | 580ms | 0kb (inline JS) |
| Hydrogen (RSC) | 1.1s | 38ms | 62kb |
| Next.js CSR | 2.9s | 1240ms | 340kb |
Liquid hızlı ama interactivity kısıtlı, CSR bundle ağır, RSC ikisinin ortası. E-ticaret için LCP 1.5s altı zorunlu (Google'ın önerisi), bu yüzden Hydrogen + RSC kombinasyonu 2026'da standart haline geldi.
Tradeoff Tablosu: Hangisini Ne Zaman Seç
| Durum | Tercih | Neden |
|---|---|---|
| Blog, docs, landing page | Full SSR/RSC | SEO öncelik, interactivity az |
| Dashboard, admin panel | Hybrid (server + client islands) | Veri fetch çok, form logic client'te |
| E-ticaret (checkout dışı) | RSC + client cart | SEO + hız dengesi |
| Real-time app (chat, collab tool) | Client-first + WebSocket | State client'te kalmalı |
| Statik içerik + form | SSG + client form island | Cache + interactivity |
Karar kriterleri:
- SEO ihtiyacı: Yüksekse server-first git
- Interactivity sıklığı: Çoksa client boundary genişlet
- Bundle budget: 100kb altı tutmalıysan server-first zorunlu
- Team expertise: RSC debug karmaşıksa hybrid başla
2024'te "her şey client-side" veya "her şey server-side" kararı veriliyordu. 2026'da bu kararı page-level bile değil, component-level veriyorsun. ProductCard server-rendered olabilir, içindeki QuickAddButton client component olabilir. Bu granülerlik hem performans hem geliştirici deneyimi kazandırıyor.
React Server Components ile Vue 3.5 arasındaki seçim artık "hangisi daha iyi" değil, "hangi yapıda daha kolay çalışırsın" sorusu. RSC bundle size'da %60+ kazandırıyor ama mental model zor. Vue 3.5 transitions daha tanıdık ama hydration metrik takibi manuel yapman gerekiyor. İkisinde de doğru yapı server-client dengesini hassas çizmekten geçiyor. Projenin ihtiyacına göre matris oluştur, ölç, iterasyon yap — bu 2026'da frontend mimarisinin temeli.