Next.js'de SSR Neden Yavaşlar?
Server-Side Rendering (SSR), kullanıcıya ilk anlamlı içeriği hızlı sunmak için güçlü bir yöntem. Ama yanlış yapılandırıldığında tam tersi etki yaratır: sunucu yanıt süreleri uzar, TTFB (Time to First Byte) artar ve kullanıcı deneyimi bozulur.
Sorunun kaynağı genellikle üç yerde gizlidir: gereksiz veri çekme işlemleri, eksik cache stratejileri ve büyük JavaScript bundle'ları. Bu yazıda Next.js SSR performansını somut tekniklerle nasıl iyileştireceğinizi anlatıyoruz.
1. Veri Çekme Katmanını Optimize Edin
SSR'da en büyük darboğaz veri çekme aşamasıdır. Sayfa render edilmeden önce sunucunun tüm veriyi hazırlaması gerekir. Bu süre uzadıkça TTFB doğrudan artar.
Paralel Veri Çekme
Birden fazla API çağrısı yapıyorsanız bunları sıralı değil paralel çalıştırın. Promise.all bu işin en temel aracıdır.
Bu basit değişiklik, üç ayrı 200ms'lik çağrıyı 600ms yerine 200ms'e düşürür.
Gereksiz Veriyi Çekmeyin
API'den dönen verinin tamamını kullanmıyorsanız, GraphQL veya API tarafında field filtering uygulayın. Büyük JSON payload'ları hem ağ hem de parse süresini artırır.
2. Cache Stratejilerini Doğru Kurun
Next.js App Router ile birlikte gelen fetch API'si yerleşik cache desteği sunar. Bunu doğru kullanmak SSR performansında en büyük farkı yaratır.
fetch Cache Seçenekleri
Her sayfanın ihtiyacına göre farklı strateji uygulayın. Sık değişmeyen veriler için revalidate değerini yüksek tutun. Kullanıcıya özel veriler için cache'i devre dışı bırakın.
Route Segment Config
Sayfa düzeyinde cache davranışını kontrol etmek için route segment config kullanabilirsiniz:
3. Streaming SSR ile TTFB'yi Düşürün
Klasik SSR'da sunucu tüm veriyi çeker, tüm HTML'i oluşturur ve tek seferde gönderir. Streaming SSR ise hazır olan kısımları anında göndermeye başlar.
Next.js App Router'da bu özellik loading.tsx ve React Suspense ile çalışır:
Bu yapıda sayfa iskeleti hemen gönderilir. UserStats ve RecentOrders bileşenleri hazır oldukça stream edilir. Kullanıcı boş bir ekran yerine anında içerik görür.
4. Bundle Boyutunu Kontrol Altında Tutun
SSR'dan dönen HTML hızlı yüklense bile, büyük JavaScript bundle'ları hydration süresini uzatır. Bu da sayfanın etkileşime geçme süresini (TTI) doğrudan etkiler.
Dynamic Import Kullanın
Sayfa yüklenirken gerekmeyen bileşenleri dinamik olarak yükleyin:
ssr: false seçeneği, bileşenin sadece istemcide yüklenmesini sağlar. Sunucu tarafında gereksiz iş yapılmasını engeller.
Bundle Analyzer ile Kontrol Edin
@next/bundle-analyzer paketini kurarak hangi modüllerin ne kadar yer kapladığını görselleştirin. Büyük kütüphaneleri (moment.js, lodash gibi) daha hafif alternatiflerle değiştirin.
5. Sunucu Bileşenleri ve İstemci Bileşenlerini Ayırın
Next.js App Router'da bileşenler varsayılan olarak Server Component'tir. Bu büyük bir avantaj: sunucu bileşenleri istemciye JavaScript göndermez.
Ama her yere 'use client' eklerseniz bu avantajı kaybedersiniz. Şu kuralı uygulayın:
- Sunucu bileşeni: Veri çekme, veritabanı sorguları, statik içerik gösterimi
- İstemci bileşeni: Event handler'lar, state yönetimi, tarayıcı API'leri
İstemci bileşenlerini mümkün olduğunca küçük tutun ve ağacın yaprak düğümlerine itin. Üst düzey layout'lar ve sayfa bileşenleri sunucu bileşeni olarak kalmalıdır.
Performansı Ölçün, Tahmin Etmeyin
Optimizasyon yapmadan önce ve sonra metrikleri ölçün. Next.js'in yerleşik next/web-vitals desteğini kullanarak Core Web Vitals verilerini toplayabilirsiniz. Özellikle şu metriklere odaklanın:
- TTFB: Sunucu yanıt süresi. Cache ve veri çekme optimizasyonlarıyla düşer.
- LCP: En büyük içerik elemanının render süresi. Streaming SSR ile iyileşir.
- TTI: Etkileşime hazır olma süresi. Bundle boyutu küçüldükçe düşer.
Ölçemediğiniz şeyi optimize edemezsiniz. Lighthouse, WebPageTest ve gerçek kullanıcı verilerini (RUM) birlikte kullanın.
Özet
Next.js SSR performans optimizasyonu tek bir ayarla çözülen bir konu değil. Veri çekme, cache, streaming, bundle yönetimi ve bileşen mimarisi birlikte çalışmalı. İşe en büyük darboğazı bulmakla başlayın, ölçün ve adım adım iyileştirin.