Next.js 14 ile App Router artık production-ready. Peki mevcut Pages Router projenizi nasıl geçireceksiniz? Bu yazıda gerçek bir projeyi adım adım migrate ettim ve öğrendiklerimi paylaşıyorum.
App Router vs Pages Router: Temel Farklar
App Router, React'ın Server Components modelini tam anlamıyla benimsiyor. Bu, Pages Router'dan köklü bir paradigma değişikliği demek.
- Varsayılan olarak Server Component:
'use client'eklemediğiniz her bileşen sunucuda çalışır - Nested layouts: Her route segmenti kendi layout'una sahip olabilir, layout state'i korunur
- Parallel ve Intercepting Routes: Modal pattern'ları artık URL-based
- Server Actions: Form submit için ayrı API route yazmaya gerek yok
Dosya Yapısı Değişiklikleri
# Pages Router pages/ index.tsx → app/page.tsx about.tsx → app/about/page.tsx blog/[slug].tsx → app/blog/[slug]/page.tsx _app.tsx → app/layout.tsx _document.tsx → app/layout.tsx (head yönetimi) api/posts.ts → app/api/posts/route.ts
getServerSideProps → async Server Component
Pages Router'daki getServerSideProps artık gerekmiyor. Bileşeni doğrudan async yapıp veri çekebilirsiniz.
// ÖNCE — Pages Router export async function getServerSideProps() { const posts = await fetchPosts(); return { props: { posts } }; } export default function Blog({ posts }) { ... } // SONRA — App Router export default async function Blog() { const posts = await fetchPosts(); // doğrudan await return <PostList posts={posts} />; }
Server Actions ile Form Yönetimi
'use server'; async function createPost(formData: FormData) { const title = formData.get('title') as string; await db.insert(posts).values({ title }); revalidatePath('/blog'); } // Client component'ta <form action={createPost}> <input name="title" /> <button type="submit">Yayınla</button> </form>
Metadata API
Her page.tsx veya layout.tsx dosyasından metadata export ederek SEO yönetimi artık çok daha temiz.
// app/blog/[slug]/page.tsx export async function generateMetadata({ params }) { const post = await getPost(params.slug); return { title: post.title, description: post.excerpt, openGraph: { images: [post.coverImage] }, }; }
Geçiş Stratejisi
- App Router ve Pages Router aynı projede birlikte çalışabilir — kademeli geçiş mümkün
- Önce
_app.tsxve_document.tsx'iapp/layout.tsx'e taşıyın - Statik sayfalardan başlayın, dinamik sayfaları sonraya bırakın
next/navigationhook'larınınext/routeryerine kullanmayı unutmayın
Performans Sonuçları
Gerçek projemizde App Router'a geçiş sonrası ölçümler:
- JavaScript bundle: 340KB → 180KB (%47 azalma)
- LCP: 2.8s → 0.9s
- TTFB: 420ms → 95ms
- Lighthouse Performance skoru: 71 → 96
Sonuç
App Router'a geçiş başlangıçta zorlayıcı görünse de, Server Components ve Server Actions'ın getirdiği sadelik ve performans kazanımları buna değiyor. Yeni projeler için doğrudan App Router ile başlamanızı öneririm.