React ve Vue sitelerinde SEO: SSR, SSG ve prerender
React ya da Vue ile yapılmış bir sitenin SEO sorunları çoğu zaman framework'ten değil, render stratejisinden çıkıyor. Aynı React bileşenleri, tarayıcıda boş bir <div id="root"> içine de basılabilir, sunucuda tam HTML olarak da üretilebilir. Google açısından bu ikisi arasında büyük fark var.
Doğru stratejiyi seçmek için önce seçeneklerin ne yaptığını netleştirmek gerekiyor. Sonra sitenin türüne bakıp karar vermek kolaylaşıyor.
Beş render stratejisi
CSR (Client-Side Rendering)
Sunucu neredeyse boş bir HTML kabuğu ve JavaScript paketleri gönderiyor. İçerik tarayıcıda, JavaScript çalıştıktan sonra oluşuyor. Create React App ya da varsayılan Vite kurulumlarının ürettiği şey bu.
Google CSR sayfaları render edebiliyor, ama içerik sadece render aşamasından sonra görünür oluyor. Render kuyruğu, engellenen kaynaklar, zincirleme API çağrıları ve SPA'larda soft 404 gibi riskler burada toplanıyor. Bu süreci Googlebot JavaScript'i nasıl işliyor yazısında ayrıntılı anlattım. Ayrıca Google dışındaki arama motorları ve birçok yapay zekâ tarayıcısı JavaScript'i hiç çalıştırmayabiliyor.
SSR (Server-Side Rendering)
Her istekte sunucu sayfayı tam HTML olarak üretiyor, tarayıcı gelen HTML'i gösteriyor ve ardından JavaScript "hydration" ile sayfayı etkileşimli hâle getiriyor. İçerik ilk HTML'de olduğu için tarayıcı ve bot aynı şeyi görüyor. Doğru durum kodunu (404, 301) sunucudan döndürmek de mümkün.
Maliyeti sunucu tarafında: her istek işlem gücü gerektiriyor ve iyi bir önbellek stratejisi olmadan TTFB yükselebiliyor.
SSG (Static Site Generation)
Sayfalar derleme (build) sırasında bir kez HTML olarak üretiliyor ve statik dosya olarak sunuluyor. En hızlı ve en ucuz seçenek. Sınırı şu: içerik değiştiğinde yeniden derleme gerekiyor. Birkaç yüz sayfalık bir blog için sorun değil, yüz binlerce ürünlü bir mağaza için pratik değil.
ISR (Incremental Static Regeneration)
SSG ile SSR arasında bir yol. Sayfa statik olarak sunuluyor ama belirli bir süre sonra ya da tetiklendiğinde arka planda yeniden üretiliyor. Next.js'te revalidate, Nuxt'ta routeRules içindeki ISR ve SWR ayarları bu işi görüyor. Büyük ve içeriği sık değişen siteler için iyi bir denge.
Prerendering
Mevcut bir CSR uygulamasını değiştirmeden, sayfaları headless bir tarayıcıyla önceden render edip statik HTML olarak kaydetmek. Az sayıda ve sabit sayfası olan bir SPA için geçici bir çözüm olabilir. Ama sayfa sayısı arttıkça ve içerik sık değiştikçe yönetmesi zorlaşıyor.
Dinamik render artık önerilmiyor
Bir dönem yaygın olan yöntem, user agent'a bakıp botlara prerender edilmiş HTML, kullanıcılara CSR sürümü göndermekti. Google bunu artık kalıcı bir çözüm olarak önermiyor ve dinamik render belgesinde bir geçici çözüm (workaround) olarak tanımlıyor; önerilen yol SSR, SSG ya da hydration ile birlikte statik render.
Dinamik render'ın pratik sorunları da var: iki ayrı sürümün bakımı, botlara giden sürümün bozulduğunu geç fark etmek ve bot tespiti hataları. Mevcut bir kurulumda çalışıyorsa hemen kaldırmanız gerekmiyor, ama yeni bir projede bu yola girmezdim.
Framework'ler
- Next.js (React): SSR, SSG ve ISR'ı sayfa bazında seçmeye izin veriyor. App Router'da React Server Components sayesinde sadece etkileşimli bileşenlerin JavaScript'i tarayıcıya gidiyor. Meta verileri
generateMetadataile yönetiliyor. - Nuxt (Vue): Varsayılan olarak SSR.
routeRulesile rota bazında prerender, ISR ya da sadece istemci tarafı render seçilebiliyor. Başlık ve meta etiketleri içinuseHeadveuseSeoMetavar. - Astro: İçerik odaklı siteler için tasarlanmış. Varsayılan olarak sıfır JavaScript ile statik HTML üretiyor; etkileşim gereken bileşenler "ada" (island) olarak ayrı ayrı hydrate ediliyor. React, Vue ya da Svelte bileşenlerini içinde kullanabiliyorsunuz.
- SvelteKit: Varsayılan olarak SSR;
export const prerender = trueile sayfa bazında statik üretime geçilebiliyor.
Rota başına head yönetimi
Hangi stratejiyi seçerseniz seçin, her rotanın kendi title, meta description, canonical ve gerekirse robots değerleri ilk HTML'de olmalı. CSR uygulamalarında sık gördüğüm sorun, bütün sayfaların index.html'deki aynı title ile başlaması ve doğru değerlerin sadece JavaScript'ten sonra gelmesi.
Next.js App Router'da bir blog yazısı sayfası şöyle görünebilir:
Burada getPost kendi veri katmanınız. notFound() çağrısından sonra durum kodunu curl -I ile kontrol etmeyi unutmayın; streaming kullanılan kurulumlarda davranış farklı olabiliyor ve benim kuralım, framework'e değil test sonucuna güvenmek.
Hydration maliyeti ve INP
SSR ve SSG içeriği ilk HTML'e taşıyor, ama JavaScript maliyetini ortadan kaldırmıyor. Tarayıcı HTML'i gösterdikten sonra bütün bileşen ağacını hydrate etmek için JavaScript'i indirip çalıştırıyor. Bu sırada ana iş parçacığı meşgul oluyor ve kullanıcının tıklamaları bekliyor.
Sonuç, sayfanın görünür olduğu ama tepki vermediği bir aralık. Bu doğrudan INP'ye yansıyor; INP'nin iyi sayılması için 75. yüzdelikte 200 ms veya altında olması gerekiyor. Hydration'ı hafifletmenin yolları:
- Etkileşim gerektirmeyen bileşenleri sunucu bileşeni (Server Component) ya da statik HTML olarak bırakmak.
- Astro adaları gibi kısmi hydration kullanmak.
- Ağır üçüncü taraf script'leri ve widget'ları ertelemek.
- Büyük bileşenleri kod bölme (code splitting) ile ayırmak.
INP tarafındaki ayrıntılar için INP'yi düzeltmek yazısına bakabilirsiniz.
Hangi site için hangisi?
| Site türü | Önerim | Neden |
|---|---|---|
| Blog, doküman, kurumsal site | SSG (Astro, Next.js, Nuxt) | İçerik seyrek değişiyor, en hızlı ve en ucuz çözüm |
| Haber sitesi | SSR veya kısa süreli ISR | İçerik dakikalar içinde güncel olmalı |
| E-ticaret (kategori, ürün) | ISR veya önbellekli SSR | Çok sayıda sayfa, değişen stok ve fiyat |
| E-ticaret (sepet, hesap) | CSR | Dizine girmesi gerekmiyor |
| Dashboard, yönetim paneli | CSR | Giriş arkasında, SEO ihtiyacı yok |
| Mevcut büyük CSR uygulaması | Önce kritik sayfalarda SSR/SSG'ye geçiş | Tamamen yeniden yazmak yerine kademeli |
| Az sayfalı, değişmeyen SPA | Build sırasında prerender | En az değişiklikle ilk HTML'i doldurmak |
Aynı sitede farklı stratejiler kullanmak normal. Modern framework'ler bunu rota bazında seçmenize izin veriyor: blog yazıları SSG, ürün sayfaları ISR, hesap sayfaları CSR olabilir.
Nasıl doğrularım?
Strateji ne olursa olsun, son kontrol aynı: sayfanın ham HTML'inde içerik, title, canonical ve linkler var mı? curl ile alınan HTML'i render edilmiş DOM ile karşılaştırmak için render farkını test etmek yazısındaki yöntemi kullanıyorum. İki sürüm arasında önemli bir fark yoksa, render stratejiniz SEO açısından işini yapıyor demektir.
Özetle
Dizine girmesi gereken sayfalar için içerik ilk HTML'de olmalı; bu da pratikte SSR, SSG ya da ISR demek. CSR'ı giriş arkasındaki sayfalara bırakın, dinamik render'ı yeni projelerde kullanmayın ve SSR'ın hydration maliyetini INP üzerinden takip edin. Seçim yaparken framework'ün popülerliğine değil, sitenizin kaç sayfası olduğuna ve içeriğin ne sıklıkla değiştiğine bakın.
Comments / questions
If you have a question about any topic or wish to contact me: Telegram or send an email to [email protected] Thanks!
Related pages
- Googlebot JavaScript'i nasıl işliyor? (2026)
- Search Console'daki her dizine ekleme durumunun Türkçe anlamı (2026)
- Sunucu logları ile SEO: cPanel loglarında Googlebot analizi (2026)
- Crawl budget gerçekten sorun mu? Hangi sitede önemli, nasıl ölçülür (2026)
- Google'ın hiç ziyaret etmediği sayfaları loglarla bulmak (2026)