aslain.dev
0%
01 Hizmetler 02 Hakkımda 03 Projeler 04 Stack 05 Blog 06 İletişim
← Tüm makaleler Web Geliştirme

Next.js App Router: app Dizini ve Nested Route Mantığı

Next.js App Router, Next.js 13 ile kararlı hale gelen ve pages/ dizininin yerini alan yeni yönlendirme sistemidir. Klasör yapısını doğrudan URL'ye çeviren bu yaklaşım, React Server Components, iç içe layout'lar ve akış (streaming) gibi yetenekleri varsayılan olarak getirir. Bu yazıda app/ dizininin nasıl çalıştığını, özel dosyaların ne işe yaradığını ve nested route mantığını gerçek örneklerle adım adım kuracağız.

app Dizini Neden Var?

Eski pages/ sisteminde her dosya bir sayfaydı ve veri çekme için getServerSideProps gibi özel fonksiyonlar gerekiyordu. App Router ise klasör tabanlıdır: bir klasör bir rota segmenti, içindeki özel dosyalar da o segmentin davranışını tanımlar. En önemli fark, bileşenlerin varsayılan olarak Server Component olmasıdır; yani tarayıcıya JavaScript göndermeden sunucuda render edilirler.

App Router'ı barındıran bir proje başlatmak için resmi kurulum aracını kullanmak en sağlıklı yoldur:

npx create-next-app@latest benim-proje
cd benim-proje
npm run dev

Kurulum sihirbazı TypeScript, ESLint ve App Router gibi seçenekleri sorar. App Router'ı seçtiğinde proje kökünde bir app/ klasörü oluşur.

Özel Dosyalar: page, layout ve Diğerleri

App Router'da klasörler rotayı oluşturur, ancak bir segmentin gerçekten erişilebilir olması için belirli adlardaki dosyalara ihtiyaç vardır. En sık kullanılanlar şunlardır:

  • page.tsx — segmentin asıl içeriğini render eder ve rotayı herkese açık (publicly accessible) hâle getirir.
  • layout.tsx — alt segmentler arasında paylaşılan, gezinti sırasında yeniden render edilmeyen kabuk.
  • loading.tsx — Suspense sınırı oluşturur; veri yüklenirken gösterilen ara durum.
  • error.tsx — segment içindeki hataları yakalayan, istemci tarafında çalışan bileşen.
  • not-found.tsx — bulunamayan içerikler için 404 arayüzü.

En basit haliyle bir ana sayfa şöyle görünür:

// app/page.tsx
export default function Home() {
  return <h1>Merhaba aslain.dev</h1>;
}

Kök Layout: Zorunlu İskelet

app/layout.tsx her App Router projesinde zorunludur çünkü <html> ve <body> etiketlerini o tanımlar. Kök layout, tüm sayfaları saran en dıştaki kabuktur ve sayfa geçişlerinde korunur:

// app/layout.tsx
export const metadata = {
  title: "aslain.dev",
  description: "Çok yönlü geliştirici portföyü",
};

export default function RootLayout({
  children,
}: {
  children: React.ReactNode;
}) {
  return (
    <html lang="tr">
      <body>{children}</body>
    </html>
  );
}

children prop'u, o layout'un içine yerleşecek alt sayfayı veya iç layout'u temsil eder. Bu, iç içe yapının temel taşıdır.

Nested Route Mantığı

İç içe rotalar, klasörleri klasörlerin içine koyarak oluşturulur. Diyelim bir blog bölümü kuruyoruz:

app/
  layout.tsx          → kök layout
  page.tsx            → /
  blog/
    layout.tsx        → /blog ve altını sarar
    page.tsx          → /blog
    [slug]/
      page.tsx        → /blog/herhangi-bir-yazi

Buradaki [slug] bir dinamik segmenttir. Köşeli parantezler, o kısmın URL'den geleceğini söyler. Değere params üzerinden ulaşırsın:

// app/blog/[slug]/page.tsx
export default async function Post({
  params,
}: {
  params: Promise<{ slug: string }>;
}) {
  const { slug } = await params;
  return <article>Yazı: {slug}</article>;
}

Next.js 15 ile birlikte params artık bir Promise'tir ve await edilmesi gerekir; bu yüzden bileşeni async tanımladık. Önemli nokta şudur: blog/layout.tsx, hem /blog hem de /blog/[slug] sayfalarını sarar, ancak kullanıcı yazıdan yazıya geçerken yeniden render edilmez. Bu, kenar çubuğu veya başlık gibi ortak öğeleri korumak için idealdir.

Sunucu ve İstemci Bileşenleri

App Router'da her bileşen aksini belirtmedikçe Server Component'tir. Etkileşim (tıklama, durum, useState, useEffect) gereken yerlerde dosyanın en başına "use client" direktifini koyarsın:

// app/components/Sayac.tsx
"use client";
import { useState } from "react";

export default function Sayac() {
  const [n, setN] = useState(0);
  return <button onClick={() => setN(n + 1)}>{n}</button>;
}

İyi bir strateji, ağacın çoğunu Server Component bırakıp yalnızca yaprak (leaf) düzeydeki etkileşimli parçaları client'a almaktır. Böylece tarayıcıya gönderilen JavaScript miktarını minimumda tutarsın.

Sayfalar Arası Gezinme

Sayfalar arasında geçiş için <a> yerine next/link bileşenini kullan. Bu, istemci tarafı geçiş (client-side navigation) ve önceden yükleme (prefetch) sağlar:

import Link from "next/link";

export default function Menu() {
  return (
    <nav>
      <Link href="/">Ana Sayfa</Link>
      <Link href="/blog">Blog</Link>
    </nav>
  );
}

Programatik yönlendirme gerektiğinde, istemci bileşenlerinde useRouter hook'unu next/navigation paketinden alırsın.

Sık Sorulan Sorular

App Router ile Pages Router aynı projede çalışır mı?

Evet. Next.js, kök seviyede hem app/ hem pages/ dizinlerinin birlikte bulunmasına izin verir; bu, mevcut projeleri kademeli olarak taşımak için tasarlanmıştır. Aynı rota her ikisinde tanımlıysa app/ önceliklidir.

page.tsx olmadan klasör eklesem ne olur?

İçinde page.tsx bulunmayan bir klasör bir URL'ye erişilemez; yalnızca düzenleme amaçlı (örneğin route grupları veya ortak bileşenler için) kullanılır. Erişilebilir bir rota için mutlaka page.tsx gerekir.

Veriyi nerede çekmeliyim?

Server Component'lerin içinde doğrudan async/await ile fetch kullanabilirsin; getServerSideProps gibi özel fonksiyonlara gerek yoktur. Next.js, fetch çağrılarını otomatik olarak önbelleğe alır ve gerektiğinde yeniden doğrular.

Next.js projeni doğru kurmak veya mevcut bir uygulamayı App Router'a taşımak mı istiyorsun? Mimariyi temiz, performanslı ve SEO uyumlu kurmana yardımcı olabilirim. Benimle iletişime geç ve projeni birlikte planlayalım.

Bu kategorideki tüm yazılar →

Devamı için