Next.js App Router: Dosya Tabanlı Routing Sistemi

Next.js App Router: Dosya Tabanlı Routing Sistemi
Next.js 13 ile tanıtılan ve Next.js 14-15 ile olgunlaşan App Router, React Server Components üzerine inşa edilmiş modern bir routing sistemidir. Dosya sistemi tabanlı bu yaklaşım, klasör yapısını doğrudan URL yapısına eşleyerek sezgisel ve güçlü bir routing deneyimi sunar. Bu rehberde App Router'ın tüm detaylarını inceleyeceğiz.
App Router vs Pages Router
Next.js iki farklı routing sistemi sunar. Yeni projelerde App Router kullanılması önerilir:
| Özellik | App Router | Pages Router (Legacy) |
|---|---|---|
| Server Components | ✅ Varsayılan | ❌ Yok |
| Nested Layouts | ✅ Yerleşik | ❌ Manuel |
| Loading UI | ✅ loading.tsx | ❌ Manuel |
| Error Handling | ✅ error.tsx | ❌ _error.tsx |
| Streaming | ✅ Destekleniyor | ❌ Sınırlı |
Dosya Tabanlı Routing Temelleri
App Router'da her klasör bir route segmenti temsil eder ve page.tsx dosyası o route'u erişilebilir kılar:
src/app/
├── page.tsx # → /
├── about/
│ └── page.tsx # → /about
├── blog/
│ ├── page.tsx # → /blog
│ └── [slug]/
│ └── page.tsx # → /blog/:slug
├── dashboard/
│ ├── layout.tsx # Dashboard layout
│ ├── page.tsx # → /dashboard
│ ├── settings/
│ │ └── page.tsx # → /dashboard/settings
│ └── analytics/
│ └── page.tsx # → /dashboard/analytics
└── (marketing)/
├── pricing/
│ └── page.tsx # → /pricing
└── features/
└── page.tsx # → /features
Özel Dosyalar
App Router, belirli amaçlar için özel dosya adları tanımlar. Bu dosyalar routing davranışını ve UI yapısını kontrol eder:
- page.tsx: Route'un UI'ını tanımlar, sayfayı erişilebilir kılar
- layout.tsx: Paylaşılan layout, alt route'ları sarar
- loading.tsx: Yükleme UI'ı, Suspense boundary oluşturur
- error.tsx: Hata UI'ı, Error boundary oluşturur
- not-found.tsx: 404 sayfası
- template.tsx: Layout benzeri ama her navigasyonda yeniden render edilir
- default.tsx: Parallel routes için fallback
Layout'lar ve İç İçe Layout'lar
Layout'lar, birden fazla sayfa arasında paylaşılan UI bileşenleridir. Alt route'lar arasında gezinirken layout yeniden render edilmez:
// src/app/dashboard/layout.tsx
import { Sidebar } from '@/components/Sidebar';
export default function DashboardLayout({
children,
}: {
children: React.ReactNode;
}) {
return (
<div className="flex">
<Sidebar />
<main className="flex-1 p-6">
{children}
</main>
</div>
);
}
// src/app/dashboard/page.tsx
export default function DashboardPage() {
return <h1>Dashboard Ana Sayfa</h1>;
}
// src/app/dashboard/settings/page.tsx
export default function SettingsPage() {
return <h1>Ayarlar</h1>;
}
template.tsx kullanın.
Route Groups
Parantez içinde yazılan klasörler route group olarak adlandırılır ve URL yapısını etkilemez. Organize etmek ve farklı layout'lar uygulamak için kullanılır:
src/app/
├── (auth)/
│ ├── layout.tsx # Auth sayfaları için özel layout
│ ├── login/
│ │ └── page.tsx # → /login
│ └── register/
│ └── page.tsx # → /register
├── (marketing)/
│ ├── layout.tsx # Marketing sayfaları için özel layout
│ ├── about/
│ │ └── page.tsx # → /about
│ └── pricing/
│ └── page.tsx # → /pricing
└── (dashboard)/
├── layout.tsx # Dashboard için özel layout
└── dashboard/
└── page.tsx # → /dashboard
Link Bileşeni ile Navigasyon
Next.js, client-side navigasyon için Link bileşeni sunar. Bu bileşen sayfaları prefetch ederek anlık geçişler sağlar:
import Link from 'next/link';
export default function Navigation() {
return (
<nav>
<Link href="/">Ana Sayfa</Link>
<Link href="/about">Hakkında</Link>
<Link href="/blog">Blog</Link>
<Link
href="/dashboard"
prefetch={false} // Prefetch'i devre dışı bırak
>
Dashboard
</Link>
</nav>
);
}
Programatik Navigasyon
Client Component'lerde useRouter hook'u ile programatik navigasyon yapabilirsiniz:
'use client';
import { useRouter } from 'next/navigation';
export default function LoginForm() {
const router = useRouter();
const handleLogin = async () => {
const success = await login();
if (success) {
router.push('/dashboard');
// veya
router.replace('/dashboard'); // History'de geri gidemez
router.refresh(); // Sunucu bileşenlerini yenile
}
};
return (
<button onClick={handleLogin}>
Giriş Yap
</button>
);
}
useRouter hook'unu next/navigation paketinden import edin, next/router'dan değil. next/router Pages Router içindir.
Aktif Link Kontrolü
Aktif sayfayı belirlemek için usePathname hook'unu kullanabilirsiniz:
'use client';
import Link from 'next/link';
import { usePathname } from 'next/navigation';
export default function NavLink({ href, children }: {
href: string;
children: React.ReactNode;
}) {
const pathname = usePathname();
const isActive = pathname === href;
return (
<Link
href={href}
className={isActive ? 'text-blue-600 font-bold' : 'text-gray-600'}
>
{children}
</Link>
);
}
Private Klasörler
Alt çizgi (_) ile başlayan klasörler routing sisteminden çıkarılır ve özel bileşenleri organize etmek için kullanılabilir:
src/app/
├── _components/ # Routing'e dahil edilmez
│ ├── Header.tsx
│ └── Footer.tsx
├── _lib/ # Routing'e dahil edilmez
│ └── utils.ts
└── page.tsx
Catch-All ve Optional Catch-All Segments
Dinamik segmentleri genişleterek birden fazla alt path'i yakalayabilirsiniz:
// [...slug]/page.tsx — Catch-all
// /shop/a → { slug: ['a'] }
// /shop/a/b → { slug: ['a', 'b'] }
// /shop/a/b/c → { slug: ['a', 'b', 'c'] }
// /shop → 404
// [[...slug]]/page.tsx — Optional Catch-all
// /shop → { slug: undefined }
// /shop/a → { slug: ['a'] }
// /shop/a/b → { slug: ['a', 'b'] }
export default function ShopPage({
params,
}: {
params: { slug?: string[] };
}) {
return <div>Slug: {params.slug?.join('/')}</div>;
}
Sonuç
Next.js App Router, dosya sistemi tabanlı yaklaşımıyla routing işlemlerini son derece sezgisel hale getirir. Layout'lar, route groups, özel dosyalar ve dinamik segmentler ile karmaşık uygulama yapılarını kolayca yönetebilirsiniz. Server Components ile varsayılan olarak gelen performans avantajları da cabası. Bir sonraki yazıda Server Components ve Client Components arasındaki farkları detaylı inceleyeceğiz.