Next.jsPerformanceCaching

Next.js Partial Prerendering ve Cache Components

Next.js Cache Components ve Partial Prerendering (PPR) ile tek bir route içinde statik hız ve dinamik kişiselleştirmeyi nasıl bir arada kullanabileceğinizi keşfedin.

Yorumlar4 dk okuma
Paylaş
Next.js Partial Prerendering ve Cache Components

Statik ve Dinamik İçeriğin Bir Arada Kullanımı

Uzun süre boyunca web geliştirmede hep aynı zorlu soruyla karşılaştık: Bu sayfa Static mi olmalı (çok hızlı ama içeriği bayat olabilir), yoksa Dynamic mi (hep güncel ama sunucu yanıtı beklendiği için yavaş)? Her şeyi Client Side Rendering'e taşımak etkileşimi çözse de, SEO ve ilk yükleme süresi (FCP) gibi konularda ciddi bedeller ödetiyordu. Next.js, Cache Components ve Partial Prerendering (PPR) ile bu denklemi kökten değiştiriyor.

Partial Prerendering (PPR), tek bir route içinde iki dünyanın en iyisini sunar: Anında yüklenen hızlı bir Static Shell ve buna paralel olarak akan (stream) Dynamic Holes.


Static Shell ve Dynamic Holes

PPR'ın mantığı oldukça nettir ve sayfa yükleme sürecini ikiye böler:

  • Static Shell (Statik Kabuk): Sayfanın iskeletidir. Layout, navbar, footer ve kullanıcıya özel olmayan genel içerikler burada yer alır. Bu kısım build anında oluşturulur ve kullanıcı siteye girdiği anda milisaniyeler içinde karşısına gelir.

  • Dynamic Holes (Dinamik Boşluklar): Sayfanın o anki kullanıcıya veya zamana bağlı olan kısımlarıdır. Kullanıcı zaten Static Shell'i görüntülerken, bu dinamik parçalar arka planda sunucuda hazırlanır ve hazır oldukları anda sayfadaki boşluklara "akar" (streaming).

Gerçek Bir Örnek: E-Ticaret Ürün Sayfası

Bu yapıyı standart bir e-ticaret senaryosu üzerinden görselleştirelim:

  • Navbar ve Logo: Her ziyaretçi için aynıdır. (Static Shell - Anında Yüklenir)

  • Ürün Başlığı ve Açıklaması: Nadiren değişir, herkes için aynıdır. (Cached Content - Shell'e dahildir)

  • Sepet Bilgisi / Size Özel Fiyat: Giriş yapmış kullanıcıya göre değişir. (Dynamic Hole - Suspense ile sonradan gelir)

Yeni Kod Yapısı

Eskiden kullandığımız export const revalidate veya force-dynamic gibi karmaşık yapılandırma objelerine artık gerek kalmadı. Bunun yerine 'use cache' direktifi ve standart React <Suspense> sınırlarını kullanıyoruz.

İşte Static, Cached ve Dynamic katmanların tek bir dosyada nasıl uyum içinde çalıştığını gösteren temiz bir örnek:

import { Suspense } from 'react';
import { cacheLife } from 'next/cache';
import { cookies } from 'next/headers';
import { Navbar } from './components/Navbar';

// 1. STATIC CONTENT
// Navbar ve sayfa düzeni Static Shell'in parçasıdır.
export default function ProductPage({ params }) {
  return (
    <main>
      <Navbar />
      
      {/* 2. CACHED CONTENT */}
      {/* Shell ile birlikte yüklenir, veri önbellekten gelir. */}
      <ProductDetails id={params.id} />

      {/* 3. DYNAMIC CONTENT */}
      {/* Suspense sayesinde sonradan stream edilir. */}
      <Suspense fallback={<div>Sepet yükleniyor...</div>}>
        <UserCart />
      </Suspense>
    </main>
  );
}

// Bileşen: Ürün Detayı (Cached)
async function ProductDetails({ id }) {
  'use cache'; // Önbellekleme direktifi
  cacheLife('hours'); // Profil: Veriyi saatlerce taze tut

  const product = await db.getProduct(id);
  
  return (
    <section>
      <h1>{product.title}</h1>
      <p>{product.description}</p>
    </section>
  );
}

// Bileşen: Kullanıcı Sepeti (Dynamic)
async function UserCart() {
  const cookieStore = await cookies(); // Dinamik render'ı tetikler
  const cartId = cookieStore.get('cartId')?.value;
  const cart = await db.getCart(cartId);

  return <div>Sepetteki ürün sayısı: {cart.totalItems}</div>;
}

Nasıl Çalışır? Kodun Analizi

Yukarıdaki kod bloğunda gerçekleşen büyü, şu dört temel kavramın birleşimiyle oluşur:

  • 'use cache': Bu direktif Next.js'e şunu söyler: "Bu fonksiyonun çıktısının bir fotoğrafını (snapshot) çek ve sakla." Bileşen veri tabanına gitse bile, her kullanıcı için tekrar tekrar çalışmaz. Bir kere çalışır ve sonucu Static Shell'in içine gömülür.

  • cacheLife('hours'): Önbellekteki verinin ne kadar süreyle "taze" kabul edileceğini belirler. Eski ISR yöntemindeki revalidate sürelerinin yerini alan, çok daha okunaklı bir yapılandırmadır. 'hours', 'days' gibi ifadelerle yönetilir.

  • cookies() (Dinamik Tetikleyici): Kod içinde cookies() veya headers() fonksiyonlarının çağrılması, Next.js için bir işarettir: "Bu bileşen kullanıcıya özeldir, bunu önceden oluşturamazsın." Bu nedenle bu bileşen otomatik olarak Dynamic moda geçer.

  • <Suspense> (Sınır Çizgisi): Bu en kritik noktadır. Dinamik olan UserCart bileşenini Suspense içine alarak, Statik ve Dinamik içerik arasına bir sınır çizersiniz. Next.js, Statik Kabuğu hemen gönderir, bu kısım için ise fallback (yükleniyor yazısı) gösterir. Veri hazır olduğunda ise gerçek içerik sayfaya akar (Streaming).

Cache Components Nasıl Aktif Edilir?

Cache Components (ve dolayısıyla PPR) şu an için opsiyonel bir özelliktir. Projenizde aktif etmek için next.config.ts dosyanıza şu ayarı eklemeniz yeterlidir:

import type { NextConfig } from 'next'

const nextConfig: NextConfig = {
  cacheComponents: true,
}

export default nextConfig

PPR’ın Avantajları

Peki neden bu mimariye geçmelisiniz? İşte sağladığı temel faydalar:

  • Performans Artışı: Static Shell anında yüklendiği için kullanıcılar beyaz bir sayfa beklemez. İlk Bayt Süresi (TTFB) minimuma iner.

  • SEO Uyumluluğu: Arama motoru botları, sayfanın statik iskeletini, başlıklarını ve ana içeriğini (Cached Content) anında görür ve tarar. Javascript'in yüklenmesini beklemek zorunda kalmazlar.

  • Daha İyi Kullanıcı Deneyimi (UX): Sayfa bütünlüğü hemen sağlanır. Kullanıcı bir kısmını görürken, diğer kısımlar (yorumlar, sepet vb.) arka planda yüklenip yerlerine yerleşir.

  • Esneklik: Aynı sayfa ağacı içinde hem çok uzun süre cache'lenen verileri hem de her saniye değişen canlı verileri karmaşık ayarlar yapmadan kullanabilirsiniz.

Yaygın Kullanım Senaryoları

PPR özellikle şu durumlarda parlar:

  • E-Ticaret Siteleri: Ürün görseli ve açıklamaları Static olarak sunulurken; stok durumu, fiyat değişimleri ve sepete ekle butonu Dynamic Hole olarak çalışır.

  • Blog Platformları: Makale içeriği SEO için Static sunulur. Ancak "Yorumlar" ve "Beğeni" sayıları kullanıcı etkileşimi olduğu için dinamik olarak sonradan yüklenir.

  • Canlı Veri Panelleri (Dashboards): Sayfanın genel çerçevesi ve menüsü Statik kalırken; canlı grafikler, bildirimler veya anlık veri akışları Dinamik olarak sayfaya akar.

Sonuç

Partial Pre-Rendering (PPR), sayfaları tamamen statik ya da tamamen dinamik olarak ayırmak zorunda kalmadan ilerlemek isteyenler için pratik bir yaklaşım sunar. Herkes için ortak olan kısımlar hızlıca yüklenirken, kullanıcıya özel veriler ihtiyaç duyulduğunda sonradan gelir. Bu yapı, uygulama mimarisini daha sade tutmaya yardımcı olurken, kullanıcı tarafında da daha akıcı ve hızlı bir deneyim sağlar. Next.js içinde PPR’ı kurmak ve kullanmak, performansla esnekliği dengeli şekilde ele almak isteyenler için mantıklı bir tercih olabilir.

Next.jsPerformanceCaching
Paylaş

Yorumlar

Henüz yorum yok. İlk yorumu sen bırak.

Sende bir yorum gönder

Okumaya devam et