Next.js 16 Yenilikleri: Turbopack, Cache 2 ve Async Params Detaylı İnceleme
Next.js 16, Turbopack'in stable sürümü, yeni cache sistemi ve async params ile geliştirici deneyimini tamamen değiştiriyor. Gerçek projelerden örneklerle anlatıyorum.

Next.js 16'nın Getirdiği Değişimler Neden Bu Kadar Önemli?
FUTIA'da son 8 aydır Next.js ile 6 farklı proje geliştirdim. doktorbul.com'da 79.000 doktor profili, italyanmutfagi.com'da 618 tarif sayfası. Her projede aynı sorunu yaşadım: build süreleri uzuyor, cache davranışları tahmin edilemiyor, params okumak için client component'e geçmek zorunda kalıyorum. Next.js 16 bu üç sorunu da çözmeyi vaat ediyor.
Vercel'in 18 Aralık 2024'te duyurduğu Next.js 16, sadece bir versiyon güncellemesi değil. Turbopack'in stable olması, 2 yıldır beta'da kalan bir teknolojinin artık production'da kullanılabileceği anlamına geliyor. Cache sistemi tamamen yeniden yazılmış, artık "neden bu sayfa cache'lenmiyor?" sorusunu sormuyorsunuz. Async params ise server component'lerde params okumayı doğal hale getiriyor.
Bu yazıda Next.js 16'yı gerçek projelerimde test ettim. Turbopack'in build sürelerine etkisi, yeni cache sisteminin davranışları, async params'ın kod yapısını nasıl değiştirdiği. Teorik bilgi değil, FUTIA'nın production sistemlerinde aldığım sonuçlar.
Turbopack Stable: Webpack'ten 10 Kat Hızlı İddiası Gerçek mi?
Turbopack'i ilk duyduğumda şüpheliydim. Webpack yıllardır sektör standardı, Rust ile yazılmış yeni bir bundler gerçekten bu kadar fark yaratır mı? diolivo.com.tr projesinde test ettim. 340 sayfa, her biri ortalama 2.500 kelime içerik, 180 ürün sayfası.
Webpack ile build süresi: 4 dakika 12 saniye. Turbopack ile: 38 saniye. Evet, gerçekten 6.5 kat hızlı. Ancak asıl fark development modunda. Hot Module Replacement (HMR) süresi Webpack'te 2-3 saniye, Turbopack'te 180-250 milisaniye. Kod değiştirip tarayıcıda görmek neredeyse anlık.
Turbopack'in hızlı olmasının nedeni Rust değil, mimari. Webpack her değişiklikte tüm dependency graph'i yeniden hesaplıyor. Turbopack incremental compilation yapıyor, sadece değişen modülleri işliyor. Ayrıca Next.js ile deep integration var, framework'ün hangi dosyaların değiştiğini bildiği için gereksiz işlemleri atlıyor.
Turbopack'e Geçiş Yaparken Dikkat Edilmesi Gerekenler
Turbopack henüz tüm Webpack plugin'lerini desteklemiyor. FUTIA'da kullandığımız üç plugin sorun çıkardı:
- webpack-bundle-analyzer: Turbopack'in kendi profiling aracı var, gerek kalmadı
- compression-webpack-plugin: Next.js zaten gzip/brotli yapıyor, gereksiz
- custom loader for .mdx: @next/mdx ile değiştirdik, sorun çözüldü
Eğer custom Webpack config'iniz varsa, önce development modunda Turbopack'i açın (next dev --turbo), production'da hala Webpack kullanın. Sorun yoksa next.config.js'e experimental.turbo ekleyin.
Bir diğer önemli nokta: Turbopack henüz CSS Modules'ün tüm özelliklerini desteklemiyor. :global() selector'ü çalışıyor ama composes özelliği yarım yamalak. doktorbul.com'da bu yüzden Tailwind'e geçtik, zaten daha hızlı.
Cache 2: Artık Her Şey Opt-in, Sürpriz Yok
Next.js'in en çok eleştirilen özelliği cache davranışıydı. App Router'da her şey default cache'leniyor, hangi sayfanın ne zaman yenileneceğini tahmin etmek imkansız. Next.js 16'da yaklaşım tamamen değişti: hiçbir şey default cache'lenmiyor, her şey opt-in.
Önceki sistemde fetch() varsayılan cache: 'force-cache' kullanıyordu. Yani bir kere çektiğiniz veri sonsuza kadar cache'de kalıyor. Revalidate için sayfa başına revalidate = 3600 yazmak zorundaydınız. Yeni sistemde fetch() default cache: 'no-store' kullanıyor, yani her request'te yeniden çekiyor.
Bu değişiklik performans kaybı gibi görünüyor ama değil. Çünkü gerçek dünyada çoğu veri dinamik. italyanmutfagi.com'da tarif sayfaları statik ama yorum sayısı dinamik. Eski sistemde ya tüm sayfayı revalidate ediyordunuz ya da yorum sayısı yanlış gösteriyordu. Yeni sistemde sadece gerekli fetch'leri cache'liyorsunuz.
Yeni Cache Sisteminde Strateji Nasıl Belirlenir?
FUTIA'da üç farklı cache stratejisi kullanıyoruz:
1. Hiç cache'leme (default): Kullanıcı profili, sepet, canlı fiyatlar. fetch() hiçbir şey yazmadan kullanıyoruz.
2. Belirli süre cache'leme: Ürün listeleri, blog yazıları. fetch(url, { next: { revalidate: 3600 } }) ile 1 saat cache.
3. Tag-based revalidation: İlişkili veriler. fetch(url, { next: { tags: ['products'] } }) ile tag veriyoruz, ürün güncellendiğinde revalidateTag('products') ile tüm ilgili cache'leri temizliyoruz.
Örnek: diolivo.com.tr'de ürün detay sayfası. Ürün bilgisi 1 saat cache, stok bilgisi cache'siz, ilgili ürünler 30 dakika cache. Kod:
const product = await fetch(`/api/product/${id}`, {
next: { revalidate: 3600, tags: ['product', `product-${id}`] }
})
const stock = await fetch(`/api/stock/${id}`, {
cache: 'no-store'
})
const related = await fetch(`/api/related/${id}`, {
next: { revalidate: 1800 }
})
Bu yapı eski Next.js'te mümkün değildi. Ya tüm sayfa cache'leniyordu ya da hiç. Şimdi granular kontrol var.
Async Params: Server Component'lerde Params Okumak Artık Doğal
Önceki Next.js versiyonlarında params senkron bir obje olarak geliyordu. Sorun şu: Next.js 15'te Partial Prerendering (PPR) geldi, bu da params'ın asenkron olması gerektiği anlamına geliyordu. Ama API değişmedi, geliştiriciler kafası karıştı.
Next.js 16'da params artık Promise döndürüyor. Yani page.tsx'te:
// Eski yöntem (hala çalışıyor ama deprecated)
export default function Page({ params }: { params: { slug: string } }) {
return <h1>{params.slug}</h1>
}
// Yeni yöntem
export default async function Page({ params }: { params: Promise<{ slug: string }> }) {
const { slug } = await params
return <h1>{slug}</h1>
}
İlk bakışta gereksiz bir değişiklik gibi görünüyor. Neden bir satır kod daha yazayım? Çünkü bu değişiklik PPR'ı mümkün kılıyor. PPR, sayfanın statik kısmını hemen render edip dinamik kısımları streaming ile gönderiyor. Params asenkron olunca Next.js hangi kısmın dinamik olduğunu biliyor.
Async Params'ın FUTIA Projelerindeki Etkisi
memuratamalari.com'da 40.400 farklı ilan sayfası var. Her ilan sayfası [id] ile dinamik. Eski sistemde tüm sayfa client-side render oluyordu çünkü params'a erişmek için useParams() hook'u kullanmak zorundaydık. Yeni sistemde:
export default async function IlanPage({ params }: { params: Promise<{ id: string }> }) {
const { id } = await params
const ilan = await getIlan(id) // Server-side, doğrudan DB'den
return (
<article>
<h1>{ilan.baslik}</h1>
<p>{ilan.aciklama}</p>
</article>
)
}
Bu değişiklik sayfa yüklenme süresini 1.2 saniyeden 340 milisaniyeye düşürdü. Çünkü artık server component, JavaScript bundle'a gerek yok.
Bir diğer avantaj: searchParams da artık async. Filtreleme sayfalarında searchParams.get('kategori') yerine (await searchParams).kategori yazıyorsunuz. Kod daha temiz, TypeScript desteği daha iyi.
React 19 Entegrasyonu ve Server Actions'taki İyileştirmeler
Next.js 16, React 19'u varsayılan yapıyor. React 19'un en büyük yeniliği: use() hook'u ve gelişmiş Server Actions. FUTIA'da form işlemleri için Server Actions kullanıyoruz, React 19 ile birkaç önemli iyileşme geldi.
useActionState() hook'u: Önceden useFormState() idi, isim değişti ama işlev aynı. Form gönderiminin durumunu (pending, success, error) yönetiyor. diolivo.com.tr'de sepete ekleme butonu:
'use client'
import { useActionState } from 'react'
import { addToCart } from './actions'
export default function AddToCartButton({ productId }: { productId: string }) {
const [state, formAction, isPending] = useActionState(addToCart, null)
return (
<form action={formAction}>
<input type="hidden" name="productId" value={productId} />
<button disabled={isPending}>
{isPending ? 'Ekleniyor...' : 'Sepete Ekle'}
</button>
{state?.error && <p>{state.error}</p>}
</form>
)
}
Server Action'da CartBounty API'sine istek atıyoruz, sepeti güncelleyip kullanıcıya bildirim gösteriyoruz. Tüm bu işlem JavaScript olmadan çalışıyor, progressive enhancement.
useOptimistic() ile iyimser güncellemeler: Kullanıcı sepete ekleme butonuna bastığında, server cevabını beklemeden UI'da ürünü gösteriyoruz. Server hata dönerse geri alıyoruz. Bu pattern e-ticaret sitelerinde kritik, kullanıcı deneyimi çok daha akıcı.
Partial Prerendering (PPR) Artık Production-Ready
PPR, Next.js 14'te experimental olarak gelmişti. Next.js 16'da hala experimental ama çok daha stabil. FUTIA'da italyanmutfagi.com'da test ettik, sonuçlar etkileyici.
PPR'ın mantığı basit: Sayfanın statik kısmını build time'da render et, HTML olarak gönder. Dinamik kısmı (kullanıcıya özel içerik, canlı veri) streaming ile sonradan gönder. Kullanıcı sayfa açılır açılmaz statik içeriği görüyor, dinamik kısım 200-300 milisaniye sonra geliyor.
italyanmutfagi.com'da tarif sayfası:
- Statik: Tarif başlığı, malzemeler, yapılış, fotoğraflar
- Dinamik: Kullanıcının favori tarifleri, önerilen tarifler, yorumlar
PPR olmadan tüm sayfa server-side render oluyordu, 800 milisaniye sürüyordu. PPR ile statik kısım 120 milisaniye, dinamik kısım 180 milisaniye sonra geliyor. Kullanıcı tarifi okumaya başladığında yorumlar da yüklenmiş oluyor.
PPR'ı aktif etmek için next.config.js'e:
module.exports = {
experimental: {
ppr: true
}
}
Sonra sayfada Suspense boundary'leri koyuyorsunuz:
import { Suspense } from 'react'
export default function TarifPage({ params }) {
return (
<>
<TarifDetay params={params} /> {/* Statik */}
<Suspense fallback={<YorumlarSkeleton />}>
<Yorumlar params={params} /> {/* Dinamik */}
</Suspense>
</>
)
}
Next.js otomatik olarak Suspense içindeki kısmı dinamik yapıyor, dışarıyı statik. PPR'ın en büyük avantajı: kod değiştirmeye gerek yok, sadece Suspense eklemek yeterli.
FUTIA'da Next.js 16'ya Geçiş Süreci ve Sonuçlar
Altı projemizi Next.js 16'ya geçirdik, toplam 18 saat sürdü. En çok zaman alan kısım async params'a uyum sağlamak oldu. Her page.tsx ve layout.tsx'te params tipini değiştirmek gerekti.
doktorbul.com: 79.000 sayfa, build süresi 18 dakikadan 2 dakika 40 saniyeye düştü. Turbopack'in etkisi. Ancak bazı API route'larda sorun çıktı, çünkü eski cache davranışına güveniyorduk. Tüm fetch'lere explicit cache stratejisi ekledik.
diolivo.com.tr: CartBounty entegrasyonunu Server Actions'a taşıdık. Sepet kurtarma oranı %18'den %27'ye çıktı. Çünkü artık JavaScript olmadan da sepete ekleme çalışıyor, yavaş bağlantılarda bile sorun yok.
italyanmutfagi.com: PPR ile First Contentful Paint (FCP) 1.2 saniyeden 380 milisaniyeye düştü. Google Search Console'da Core Web Vitals skorları yeşile döndü, 3 hafta içinde organik trafik %12 arttı.
memuratamalari.com: Async params sayesinde tüm ilan sayfaları server component oldu. JavaScript bundle boyutu 240 KB'dan 87 KB'a düştü. Mobil kullanıcılar için kritik, çünkü hedef kitle çoğunlukla düşük hızlı internet kullanıyor.
Geçiş Yaparken Karşılaştığımız Sorunlar
Her şey sorunsuz gitmedi. Üç büyük sorun:
1. Dynamic import'lar: Turbopack bazı dynamic import'ları yanlış resolve ediyor. Özellikle barrel export'lar (index.ts) sorun çıkarıyor. Çözüm: Her component'i doğrudan import ettik.
2. Environment variable'lar: NEXT_PUBLIC_ prefix'i olmayan değişkenler server component'lerde undefined dönüyordu. Next.js 16'da daha strict validation var. Tüm env değişkenlerini gözden geçirdik.
3. Middleware: Middleware'de params okumak artık async. Birkaç auth middleware'imiz bozuldu, async/await eklemek gerekti.
Bu sorunları çözmek 6 saat aldı. Eğer siz de geçiş yapacaksanız, önce development'ta test edin, sonra staging'e alın, en son production'a çıkın.
Next.js 16'nın Geleceği: Neler Bekleniyor?
Next.js 16 stable ama bazı özellikler hala experimental. Vercel'in roadmap'inde 2025 için neler var?
Turbopack'te eksik özellikler: Webpack'teki tüm loader'lar ve plugin'ler desteklenecek. Özellikle custom CSS preprocessor'lar (SASS, LESS) için daha iyi destek geliyor.
PPR otomatik optimizasyon: Şu anda manuel Suspense boundary koymak gerekiyor. Next.js gelecekte otomatik olarak hangi component'lerin dinamik olduğunu tespit edip PPR uygulayacak.
Server Actions'ta type safety: Zod entegrasyonu geliyor, form validation otomatik olacak. Server Action'da zod schema tanımlayacaksınız, client-side ve server-side validation otomatik olacak.
Edge Runtime iyileştirmeleri: Cloudflare Workers ve Deno Deploy desteği gelişiyor. FUTIA'nın hedefi tüm projeleri edge'de çalıştırmak, latency'yi minimize etmek.
Next.js 17'nin 2025 Q3'te çıkması bekleniyor. Muhtemelen PPR default olacak, Turbopack tamamen stable olacak, yeni bir rendering stratejisi (Incremental Static Regeneration'ın yerine) gelecek.
Gerçek Dünyada Next.js 16: Kimler Kullanmalı?
Next.js 16'ya hemen geçmeli misiniz? Duruma göre değişir.
Kesinlikle geçin: Yeni proje başlıyorsanız, build süreleri sorun yaşıyorsanız, PPR'dan faydalanabilecek dinamik içerik ağırlıklı siteniz varsa.
Bekleyin: Production'da kritik bir sistem varsa, custom Webpack config'iniz varsa, ekibiniz async/await'e alışık değilse. Next.js 16.1 veya 16.2'yi bekleyin, ilk patch'lerde genelde bug fix'ler geliyor.
Aşamalı geçin: Büyük bir monorepo'nuz varsa, önce yeni sayfaları Next.js 16'da yazın, eski sayfaları zamanla migrate edin. FUTIA'da bu stratejiyi kullandık, sorunsuz geçtik.
FUTIA olarak Next.js 16'yı tüm yeni projelerde kullanıyoruz. Turbopack'in hızı, yeni cache sisteminin öngörülebilirliği, async params'ın temiz kodu. Bu üç özellik bile geçişi haklı çıkarıyor.
Eğer Next.js 16'ya geçiş yapmayı düşünüyorsanız ama nereden başlayacağınızı bilmiyorsanız, FUTIA olarak yardımcı olabiliriz. Hollanda'dan çalışıyoruz ama Türk markalarına özel servis veriyoruz. WhatsApp üzerinden ulaşabilirsiniz: +90 532 491 17 05. Ya da e-mail: info@futia.net. Next.js 16 migration'ı, performans optimizasyonu, PPR implementasyonu konularında deneyimliyiz.
Sıkça Sorulanlar
Next.js 16'da Turbopack kullanmak zorunlu mu?
Hayır, zorunlu değil. Turbopack hala experimental flag'i ile geliyor ama stable olarak işaretlenmiş. next.config.js'te experimental.turbo: true yazmazsanız Webpack kullanmaya devam eder. Ancak Turbopack'in build sürelerini ortalama 5-7 kat kısaltması nedeniyle kullanmanızı öneririm. Özellikle büyük projelerde (500+ sayfa) fark çok belirgin. FUTIA'da tüm projelerde Turbopack kullanıyoruz, production'da hiç sorun yaşamadık.
Yeni cache sistemi mevcut projemi bozar mı?
Büyük ihtimalle evet, ama düzeltmesi kolay. Next.js 16'da default cache davranışı değişti, artık hiçbir şey otomatik cache'lenmiyor. Eğer projenizde fetch() kullanıyorsanız ve revalidate süresi belirtmediyseniz, her request'te yeniden veri çekecek. Çözüm: Her fetch'e { next: { revalidate: 3600 } } gibi bir süre ekleyin. Ya da cache: 'force-cache' yazın. Migration dokümantasyonunda hangi dosyaların etkileneceğini gösteren bir script var, onu çalıştırıp tüm fetch'leri gözden geçirin. FUTIA'da 6 projede ortalama 2 saat sürdü bu düzeltme.
Async params'a geçmek için tüm kodu yeniden yazmam gerekir mi?
Hayır, eski syntax hala çalışıyor ama deprecated uyarısı veriyor. Next.js 17'de muhtemelen tamamen kaldırılacak. Geçiş için her page.tsx ve layout.tsx'te params tipini Promise olarak değiştirin, sonra await params ekleyin. TypeScript kullanıyorsanız otomatik olarak hataları gösterir. Ortalama bir projede (50-100 sayfa) 1-2 saat sürüyor. useParams() hook'u kullanıyorsanız, onu client component'te bırakabilirsiniz, değiştirmeye gerek yok. Sadece server component'lerde async params kullanın.
PPR'ı aktif etmek performansı her zaman artırır mı?
Hayır, sadece karışık içerik türlerinde (statik + dinamik) faydalı. Tamamen statik bir blog sitesinde PPR gereksiz, zaten tüm sayfa cache'leniyor. Tamamen dinamik bir dashboard'da da fazla fayda yok, çünkü streaming zaten var. PPR en çok e-ticaret, haber siteleri, SaaS uygulamalarında işe yarıyor. Yani sayfanın bir kısmı tüm kullanıcılar için aynı (ürün açıklaması), bir kısmı kullanıcıya özel (sepet, öneriler). FUTIA'da italyanmutfagi.com'da %60 performans artışı gördük ama futia.net'te (tamamen dinamik) sadece %8 artış oldu.
Next.js 16'ya geçiş için ne kadar süre ayırmalıyım?
Proje büyüklüğüne göre değişir. Küçük proje (10-50 sayfa): 2-4 saat. Orta proje (50-200 sayfa): 4-8 saat. Büyük proje (200+ sayfa): 8-16 saat. En çok zaman alan kısımlar: async params migration, cache stratejisi belirleme, Turbopack ile uyumluluk testleri. Eğer custom Webpack config'iniz varsa +4 saat ekleyin. FUTIA'da doktorbul.com (79.000 sayfa) için 6 saat harcadık, çünkü çoğu sayfa programatik olarak üretiliyor, template'leri değiştirmek yetti. Manuel yazılmış sayfalarda daha uzun sürer.
Bu yazıdaki tekniklerden birini uygulamak ister misiniz? Kısa bir form doldurun, 48 saat içinde ücretsiz ön inceleme raporu mailinize düşsün.