Next.js App Router ile rota yapısı kurmak: klasörden sayfaya adım adım
Beceri rehberi

Next.js App Router ile rota yapısı kurmak: klasörden sayfaya adım adım

Hazırlayan: Mindset Institute EditörlüğüGüncellendi: 6 dk okuma

Next.js App Router'da klasörlerle rota kurma, page ve layout dosyaları, dinamik segmentler, Link ile gezinme ve yükleme durumları adım adım anlatılıyor.

App Router'da rota nasıl tanımlanır?

App Router'da yönlendirme dosya sistemine dayanır: app klasörünün altındaki klasörler URL parçalarını, bu klasörlerin içindeki özel adlı dosyalar ise o parçada gösterilecek arayüzü belirler. Yani rota tanımlamak için ayrı bir yönlendirme tablosu yazmazsınız; klasörü açarsınız, içine bir page dosyası koyarsınız ve o yol yayına çıkar.

Bu modelin temel taşları şunlardır. Klasörler rota segmentlerini oluşturur. Dosyalar ise o segmentte ne gösterileceğini söyler. En çok kullanacağınız dosyalar page ve layout dosyalarıdır. Bir klasörde page dosyası yoksa o yol dışarıdan erişilebilir bir sayfa olmaz; klasör yalnızca altındaki yolların kabı olarak kalır.

Her yeni projede ilk yapılacak iş, app klasörünün altında kök layout ile ana sayfayı ayağa kaldırmaktır. Sonraki bölümlerde bu dosyaları sırayla kuracağız.

İlk sayfa ve kök layout

Ana sayfa, app klasöründeki page dosyasıdır ve bir React bileşenini varsayılan olarak dışa aktarır:

// app/page.tsx export default function Page() { return <p>Merhaba Next.js</p> }

Page dosyası tek başına yetmez; her uygulamanın bir kök layout'u olmalıdır. Kök layout zorunludur ve html ile body etiketlerini içermelidir. Sayfalar ve iç layout'lar children özelliği üzerinden bunun içine yerleşir:

// app/layout.tsx export default function RootLayout({ children }: { children: React.ReactNode }) { return ( <html lang="tr"> <body> <main>{children}</main> </body> </html> ) }

Layout, birden çok sayfa arasında paylaşılan arayüzdür: üst menü, yan menü, altbilgi gibi parçalar buraya konur. Gezinme sırasında layout'lar durumlarını korur, etkileşimli kalır ve yeniden çizilmez. Bu yüzden menüye yazdığınız arama kutusunun içeriği sayfa değiştirseniz de kaybolmaz.

Sık yapılan hata, html ve body etiketlerini kök layout'a koymayı unutmaktır; kök layout zorunlu olduğu için bu eksiklik uygulamanın çalışmasını engeller.

İç içe rotalar ve dinamik segmentler

Klasörleri iç içe açarak iç içe rotalar kurarsınız. Blog listesi için app içinde blog adlı bir klasör açıp içine page dosyası koyduğunuzda yol blog olur. Tek bir yazıyı göstermek için blog klasörünün içine köşeli parantezli bir klasör açarsınız:

// app/blog/[slug]/page.tsx export default async function BlogYazisi({ params, }: { params: Promise<{ slug: string }> }) { const { slug } = await params const yazi = await yaziGetir(slug) return <article>{yazi.baslik}</article> }

Köşeli parantezli klasör, dinamik segment olarak adlandırılır ve veriden birden çok sayfa üretmek için kullanılır: blog yazıları, ürün sayfaları, kategori sayfaları gibi. params değeri bir söz olarak (Promise) gelir; kullanmadan önce await ile açmanız gerekir. Bunu unutmak tipik bir hata kaynağıdır.

Dinamik rotaların hangi değerler için derleme zamanında üretileceğini belirlemek isterseniz aynı dosyada generateStaticParams fonksiyonunu tanımlarsınız; bu fonksiyonun içeriğini veri kaynağınıza göre doldurursunuz.

İç içe layout'lar ve ortak arayüz

Layout'lar klasör hiyerarşisini izleyerek iç içe geçer. Kök layout her şeyi sarar; blog klasörüne koyduğunuz layout dosyası ise yalnızca blog altındaki sayfaları sarar:

// app/blog/layout.tsx export default function BlogLayout({ children }: { children: React.ReactNode }) { return <section>{children}</section> }

Sonuçta kök layout, blog layout'unu, o da blog sayfasını ve tek yazı sayfasını sarmalar. Böylece blog bölümüne özgü bir kenar çubuğunu tek yerde tanımlar, bütün blog sayfalarında kullanırsınız.

Burada pratik bir ilke vardır: ortak arayüzü mümkün olan en alt ortak klasöre koyun. Bir kenar çubuğu yalnızca yönetim ekranlarında gerekiyorsa bunu kök layout'a değil, o bölümün layout'una yerleştirin. Aksi hâlde alakasız sayfalar da gereksiz bileşenleri taşır.

Layout'lar sayfalar arası geçişte yeniden çizilmediği için kullanıcıya özgü kontrolleri (örneğin oturum doğrulaması) yalnızca layout'ta yapmak güvenli değildir; kontrolü veriye en yakın yerde, yani sayfada ya da veri erişim katmanında yapın.

Link ile gezinme ve arama parametreleri

Sayfalar arasında gezinmenin ana yolu, next/link paketindeki Link bileşenidir. Link, HTML a etiketini genişletir; ön yükleme ve istemci tarafı geçiş sağlar:

import Link from 'next/link'

<Link href={'/blog/' + yazi.slug}>{yazi.baslik}</Link>

Arama parametrelerini (adresteki soru işaretinden sonraki kısım) okuma biçimi, nerede kullanacağınıza göre değişir. Sunucu bileşeni olan bir sayfada searchParams özelliğini kullanırsınız; bu da sayfayı dinamik üretime geçirir, çünkü değer her istekte gelir. Yalnızca istemcide ihtiyacınız varsa, örneğin zaten yüklenmiş bir listeyi süzmek için, useSearchParams kancasını kullanırsınız. Basit bir kural: parametre sayfanın veri yüklemesini belirliyorsa (sayfalama, veritabanı süzmesi) searchParams, yalnızca arayüzü etkiliyorsa useSearchParams.

Daha gelişmiş gezinme gerektiğinde useRouter kancası vardır; ancak mümkün olduğu sürece Link tercih edilmelidir, çünkü ön yükleme avantajını kendiliğinden getirir.

Yükleme durumları ve hata sınırları

Veri çeken bir sayfa yavaş yanıt verirse kullanıcı boş ekrana bakmasın diye aynı klasöre bir loading dosyası koyabilirsiniz:

// app/blog/loading.tsx export default function Loading() { return <div>Yükleniyor...</div> }

Bu dosya, sayfayı otomatik olarak bir Suspense sınırına sarar. Gezinme sırasında kullanıcı hemen layout'u ve yükleme durumunu görür, içerik hazır olunca yerine geçer. Sayfanın yalnızca bir bölümü yavaşsa, o bölümü doğrudan Suspense ile sarıp yedek arayüzü orada göstermek daha ince bir kontrol sağlar.

Bir istisnaya dikkat edin: layout, çerez ya da önbelleğe alınmamış veri gibi istek anında çözülen bir şeye erişiyorsa kendi klasöründeki loading dosyası onu kapsamaz; gezinme layout hazır olana kadar bekler. Bu durumda yavaş erişimi kendi Suspense sınırı içine alın ya da veri çekmeyi sayfaya taşıyın.

Hataları yakalamak için aynı mantıkla error dosyasını kullanırsınız; böylece bir bölümdeki hata bütün uygulamayı çökertmez.

Başlarken sık yapılan hatalar

Kök layout'ta html ve body etiketlerini unutmak, uygulamanın açılmamasının en sık sebebidir. Dinamik segmentte params değerini await etmeden kullanmak, bir diğer sık hatadır. Klasörde page dosyası olmadığı hâlde o yola gitmeyi beklemek de tipik bir yanılgıdır.

Bir başka alışkanlık hatası, her şeyi tek bir büyük layout'a doldurmaktır; bu hem gereksiz bileşen yükler hem de bölümler arası bağımsızlığı bozar. Rota yapısını planlarken önce ekranları ve ortak arayüz bölgelerini bir kâğıda çizin, ardından klasör ağacını bu çizime göre kurun.

En sağlıklı başlangıç, küçük bir örnekle denemektir: ana sayfa, blog listesi ve tek yazı sayfasından oluşan bir iskelet kurun, her seviyeye bir layout ekleyin, yavaş bir veri kaynağı taklit edip loading dosyasının davranışını gözlemleyin. Böylece dosya adlarının ne yaptığını ezber yerine deneyimle öğrenirsiniz.

Bu beceriyi Mindset programlarında nerede çalışırsınız

Next.js ile Full-Stack Web Uygulamaları programı, React biliyor ve bunu sunucu tarafı ile birleştirmek isteyen geliştiriciler için tasarlanmıştır. Modül başlıkları arasında App Router mimarisi, veri getirme ve önbellekleme, veri değiştirme ve form akışları, kimlik doğrulama ve yetkilendirme, performans ve kullanıcı deneyimi ile test, dağıtım ve gözlemlenebilirlik yer alır.

Kurumsal ekipler için bu sıralama, bir web ürününü tek bir çatı altında ele alıp rota yapısından üretim ortamına kadar aynı konvansiyonla çalışmaya imkân verir; rota mimarisi ilk modülde ele alındığı için ekip bu dili baştan ortak kurar.

İlgili Mindset programı

Next.js ile Full-Stack Web Uygulamaları

Sık sorulanlar

Sık sorulan sorular

Pages Router ile App Router arasındaki fark nedir?

App Router, klasör tabanlı rota, iç içe layout ve varsayılan olarak sunucu bileşenleri sunan yapıdır; sayfalar ve layout'lar sunucuda çalışır, etkileşim gereken parçalar istemci bileşeni olarak eklenir. Pages Router ise Next.js'in önceki yönlendirme sistemidir. Yeni bir projeye başlıyorsanız güncel dokümantasyon App Router üzerinden ilerler.

Her klasörün içine page dosyası koymam gerekir mi?

Hayır. Yalnızca dışarıdan erişilebilir olmasını istediğiniz yollarda page dosyası gerekir. Sadece altında başka rotalar barındıran ya da düzen amaçlı klasörler page dosyası olmadan da var olur. Bir klasörde page yoksa o yola doğrudan gidildiğinde sayfa bulunamaz.

Layout içinde veri çekebilir miyim?

Evet, layout bir sunucu bileşenidir ve veri çekebilir. Yalnızca çerez ya da önbelleğe alınmamış veri gibi istek anında çözülen erişimlerin, aynı klasördeki loading dosyasıyla kapsanmadığını unutmayın. Böyle erişimleri kendi Suspense sınırında tutmak ya da veri çekmeyi sayfaya taşımak gerekebilir.

Dinamik segmentte params neden await edilir?

Güncel dokümantasyonda params ve searchParams değerleri bir söz (Promise) olarak tanımlanır. Bu yüzden sayfa bileşenini async yapıp değeri await ile açarsınız; açmadan doğrudan özelliklerine erişmeye çalışmak yanlış sonuç ya da tip hatası üretir. Örnek kod bu kullanımı gösterir.

Next.js App Router Kullanımı: Sayfa, Layout, Rota