Next.js 14 ile 15 arasındaki fark, API yüzeyinde sınırlı kalıyor gibi görünse de çalışma zamanı davranışında köklü değişiklikler var. Caching varsayılanları tersine döndü, Turbopack geliştirme ortamında kararlı hale geldi, React 19 entegrasyon gerektirmeden pakete girdi. Bu üç değişiklik farklı profillere sahip: biri elle müdahale ister, biri otomatik devreye girer, biri hâlâ opt-in.

Yükseltmeyi planlayan ekiplerin en çok takıldığı soru şu: "Performans değişiklikleri bizim tarafımızda bir şey gerektirir mi?" Yanıt kısmen hayır, fakat önemli bir evet de içeriyor. Caching değişikliği fark edilmezse mevcut sayfalar her istekte veritabanına gidiyor; yüksek trafikli uygulamalarda bu anında hissedilen bir gerilme demek.

Caching varsayılanı, Turbopack ve React 19 ayrı ayrı ölçülür: ne değişti, neden değişti, ne zaman gerçekten kazandırıyor, ne zaman beklenmedik sonuç üretiyor.

Caching Varsayılanları Neden Tersine Döndü?

Next.js 14'te fetch çağrıları varsayılan olarak önbellekleniyordu. Aynı URL'ye yapılan birden fazla istek tekil bir network çağrısına indirgeniyor, sonuç Data Cache'e yazılıyordu. Pek çok ekip bunu fark etmeden kullanıyordu; sayfa hızlı görünüyor, stale veri riski görünmüyordu.

Next.js 15'te bu varsayılan tersine döndü. fetch çağrıları artık cache: 'no-store' ile başlıyor. Her istek fresh data döndürür; ziyaretçiden ziyaretçiye state taşınmaz. Bu değişikliğin pratik anlamı şu: önceki davranışa güvenen ve açık bir revalidate ayarı olmayan sayfalar, artık her request'te upstream kaynağa gidiyor.

Sık değişen veriler için bu haber iyi. Stale content gönderme riski ortadan kalkar. Ama yoğun trafik altında çalışan, nadiren değişen içerik sunan sayfalar için ekstra veritabanı ya da API yükü anlamına gelir; ve bu yük sessizce birikerek önceki versiyonda hiç görünmemiş darboğazlar yaratabilir. Eski davranışa dönmek için iki yol var: ya fetch(url, { cache: 'force-cache' }) ile istek bazında ayarlayın ya da Route Segment Config ile tüm segment için export const revalidate = 3600 yazın. Saniye cinsinden verilen bu değer, segmentin ne kadar süreyle önbellekte tutulacağını belirler.

cookies(), headers() ve searchParams API'leri de Next.js 15'te değişti. Bu üçü çağrıldığında sayfa otomatik olarak dynamic rendering moduna geçiyor; önceki sürümde bu geçiş daha örtük gerçekleşiyordu. Bunlara ek olarak söz konusu API'ler artık promise döndürüyor: await cookies() şeklinde çağrılması gerekiyor. await eksik kalırsa runtime hatası alırsınız ve Next.js'in sağladığı codemod aracı bu dönüşümü büyük ölçüde otomatik çözüyor.

Turbopack Geliştirme Ortamında Kararlı Hale Geldi

Next.js 15 ile birlikte Turbopack, dev ortamında kararlı sürüme ulaştı. next dev --turbopack komutu artık deneysel bir bayrak değil, desteklenen bir mod. Production build için çalışmalar sürüyor; fakat tam webpack pariteye henüz ulaşılmadı.

Dev sunucusunda fark en belirgin biçimde büyük projelerde hissediliyor. Webpack tabanlı başlatma, Rust tabanlı paralel derlemeyle yer değiştiriyor; HMR güncellemesi bir bileşen değişikliğinde milisaniyeler içinde tamamlanıyor. Yüzlerce bileşene ve çok sayıda route'a sahip projelerde ilk derleme süresi ciddi biçimde kısalıyor. Küçük, az sayfalı uygulamalarda ise fark ihmal edilebilir düzeyde kalabilir. Kıyaslama yapmak için aynı projede önce next dev, ardından next dev --turbopack çalıştırıp terminal çıktısındaki "compiled in" süresini karşılaştırmak yeterli bir başlangıç noktası.

Bununla birlikte Turbopack her projede sorunsuz çalışmaz. Özel Webpack loader'larına, CSS Modules dışı stil araçlarına veya belirli Babel eklentilerine bağımlı projelerde uyumsuzluk çıkabilir. Kararlı olmak, "her yapılandırmada çalışır" garantisi değil. Turbopack'i denemek ayrı bir branch üzerinde test etmek demek; canlıya geçmeden önce build çıktısını ve uygulama davranışını doğrulamak gerekiyor.

React 19 Entegrasyonu: Otomatik Gelen Değişiklikler

Next.js 15, React 19'u birlikte getiriyor. Ayrı bir yapılandırma gerekmez; yükseltme yapıldığında React 19 otomatik aktif olur.

React 19'un en dikkat çekici yeniliği Actions mekanizması. useActionState ve useFormStatus hook'ları form submission ve mutation işlemlerini daha doğrudan bir biçimde yönetmeye olanak tanıyor. Bunlar birincil olarak geliştirici deneyimine yönelik; ancak yanlış kurulmuş state güncellemelerinden kaynaklanan gereksiz re-render'ları da azaltıyor.

React Compiler ise opt-in olarak geliyor. Etkinleştirdiğinizde derleyici, useMemo ve useCallback çağrılarını otomatik olarak ekleyip kaldırmaya çalışır; memoizasyon kararlarının nerede gereksiz hale geldiğini sizin yerinize ele almayı hedefler. Fakat henüz her proje için uygun değil. Karmaşık özel hook zinciri olan, dış kütüphane ile yoğun entegrasyon yapan ya da Proxy tabanlı state yöneten projelerde derleyici beklenmedik sonuç üretebilir. Etkinleştirmeden önce küçük bir route segment üzerinde test edip React DevTools Profiler ile davranışı doğrulamak gerekiyor.

Hidrasyon hataları da React 19 ile değişti. Önceki sürümde sunucu ve istemci çıktısı arasındaki uyuşmazlık tüm ağacı yeniden render ederdi. Artık yalnızca uyuşmazlık olan alt ağaç yeniden hidrate ediliyor. Büyük sayfalarda bu fark ölçülebilir: ilk etkileşime hazır olma süresi kısalıyor.

Server Components ve Paralel Veri Çekme

Server Components, Next.js 13'ten beri var; 15. sürümde daha olgunlaştı. Temel kural değişmedi: sunucuda render edilen bileşenler istemci bundle'ına girmez. Bu, JavaScript gönderme maliyetini düşürmenin en doğrudan yolu.

Veri çekme tarafında belirleyici bir ilke var: bağımsız veriler paralel çekilmeli. Bir içerik sayfasında başlık, yazar bilgisi ve ilgili yazılar birbirinden bağımsızsa sıralı await yerine Promise.all kullanmak toplam gecikmeyi en yavaş isteğin süresine indirir; sıralı çekimde her gecikme bir öncekinin üstüne yığılır.

// Sıralı: süreler toplanır
const post = await fetchPost(slug);
const author = await fetchAuthor(post.authorId);
const related = await fetchRelated(slug);

// Paralel: en yavaşın süresi kadar bekler
const [post, related] = await Promise.all([
  fetchPost(slug),
  fetchRelated(slug)
]);
const author = await fetchAuthor(post.authorId);

author burada post.authorId'ye bağımlı olduğundan sıralı kalıyor; bağımsız olanlar paralele alındı. Bu ayrımı doğru yapmak, bileşen ağacındaki render maliyetini doğrudan etkiler.

Suspense ile birleştirildiğinde Server Components bir başka avantaj sunuyor: sayfanın tamamını bekletmeden bölüm bölüm akıtma (streaming). Hazır olan içerik önce gönderilir, geç tamamlanan veriler hazır olunca akar. Next.js 15'te bu mekanizma daha az edge case bırakacak biçimde iyileştirildi; özellikle iç içe geçmiş Suspense sınırlarındaki davranış tutarlı hale geldi.

Partial Prerendering: Ne Zaman İşe Yarar, Ne Zaman Gereksiz?

Partial Prerendering (PPR), Next.js 15'te hâlâ deneysel. Etkinleştirmek için next.config.js'de experimental.ppr: 'incremental' ayarını ve ardından ilgili route'ta export const experimental_ppr = true satırını eklemek gerekiyor.

PPR'ın mantığı şu: sayfanın statik kısmı önceden oluşturulup CDN'den sunulur; dinamik kısımlar Suspense sınırlarına göre akıtılır. İlk bayt süresi (TTFB) tamamen statik bir sayfayı andırır, fakat kullanıcı dinamik içeriği de alır. E-ticaret ürün sayfaları bunun için doğal bir seçim; ürün başlığı, açıklaması ve görseli statik tutulabilir, stok durumu ve kullanıcıya özel fiyat dinamik kalır.

PPR ters etki ürettiği durumlar da var. Sayfanın büyük bölümü dinamikse ya da Suspense sınırları çoksa statik kısım küçük kalır ve PPR'ın getirdiği ekstra karmaşıklık kazanımı siler. Sayfayı bölümlere ayırmadan, neyin statik tutulabileceğini haritalarlamadan PPR etkinleştirmek anlamsız. İlk adım: sayfadaki her veri kaynağını "her saat değişir mi, her istemci için farklı mı?" diye sınıflandırmak.

Geçiş Sırasında Kırılabilecek Noktalar

Yükseltme otomatik iyileştirmeler getirse de birkaç alan elle müdahale istiyor. Caching değişikliği zaten ele alındı; bunun dışında iki alan daha öne çıkıyor.

next/image bileşeninin varsayılan sizes hesaplaması değişti. Önceki sürümde görsel daha geniş bir viewport için optimize edilirdi; şimdi hesaplama daha granüler. sizes prop'unu açıkça belirtmek en güvenli yol: bunu yapmadan yayına çıkmak, bazı ekranlarda gereğinden büyük görsel indirilmesi riskini taşıyor. next/font ile yüklenen yazı tiplerinde ise font-display varsayılanı optional'a döndü; CLS açısından daha güvenli, fakat önceki swap davranışını tercih ediyorsanız bunu açıkça belirtmeniz gerekiyor.

Middleware'de ince davranış farkları da var. Route gruplarıyla çalışan matcher yapıları ve auth katmanları geçiş sonrası test edilmeli. Bir diğer pratik adım: npx @next/codemod@latest upgrade komutu ile Next.js'in sunduğu codemod aracını çalıştırmak. Bu araç, promise döndüren API çağrılarındaki eksik await'leri ve benzer mekanik değişiklikleri büyük ölçüde otomatik çözüyor; birçok kırılma noktasını elle aramaktan kurtarıyor.

Next.js 14'ten 15'e geçiş, salt versiyon numarası değiştirmenin ötesinde bilinçli bir değerlendirme istiyor. Turbopack ve React 19 doğrudan kazanım sağlar; caching tersine dönüşü ise her sayfanın mevcut davranışına göre ayrı ayrı gözden geçirilmeli. İkisini karıştırmak, beklenmedik performans gerilmelerine neden olabilir.

Geçişi küçük adımlarla yapmak, her adımda ölçmek ve değişiklikleri izole etmek en sağlam yol. Hangi optimizasyonun gerçekten kazandırdığını anlamak için tüm sayfaları aynı anda göçürmek yerine bir route grubunu pilot olarak alıp geri kalanla kıyaslamak etkiyi somutlaştırır. Yükseltme sonrası yayına çıkmadan önceki kontrol adımları arasına caching davranışını doğrulayan bir smoke test eklemek faydalı; özellikle sık erişilen sayfaların her istekte upstream'e gittiğini ya da beklendiği gibi önbelleklendiğini teyit etmek gerekiyor.

Yükseltme sonrası gözlemlemesi en zor alan genellikle caching regresyonlarıdır; çünkü bunlar hata değil, sessiz davranış değişikliğidir. Sayfa hâlâ çalışır, fakat her istekte upstream'e gittiği için yük altında tepki süresi geriler. Versiyon yükseltmesini tek başına bir performans kazanımı olarak değil, caching stratejisini yeniden gözden geçirme fırsatı olarak değerlendirmek daha gerçekçi bir yaklaşım. Sessiz kalan bu tür sorunların zamanla nasıl biriktiğini anlamak, yükseltme kararlarını daha temkinli almayı sağlar.