Türkçe

Next.js'in App Dizini'ndeki dönüştürücü dosya tabanlı yönlendirme sistemini keşfedin. Bu sistem, modern web uygulamaları için gelişmiş organizasyon, performans ve geliştirici deneyimi sunar.

Next.js App Dizini: Dosya Tabanlı Yönlendirmede Bir Devrim

Next.js, geliştiricilere performanslı, ölçeklenebilir ve kullanıcı dostu uygulamalar oluşturmaları için güçlü araçlar ve özellikler sunarak web geliştirmenin sınırlarını sürekli olarak zorlamıştır. App Dizini'nin tanıtılması, özellikle dosya tabanlı yönlendirmeye getirdiği yenilikçi yaklaşımla ileriye doğru atılmış önemli bir adımı temsil etmektedir. Bu makale, App Dizini'nin yönlendirme mekanizmasını derinlemesine inceleyerek avantajlarını, temel kavramlarını ve Next.js ile modern web uygulamaları oluşturmadaki pratik sonuçlarını araştırmaktadır.

Next.js'te Yönlendirmenin Evrimini Anlamak

App Dizini'nden önce, Next.js yönlendirme için Pages Dizini'ne güveniyordu. Etkili olmasına rağmen, bu yaklaşımın belirli sınırlamaları vardı. Pages Dizini, `pages` dizinindeki her dosyanın bir rotaya karşılık geldiği basit bir dosya tabanlı yönlendirme sistemi kullanıyordu. Örneğin, `pages/about.js` `/about` rotasına eşlenirdi.

Basit olmasına rağmen, Pages Dizini karmaşık layout'lar, veri çekme stratejileri ve sunucu tarafı render etme kalıpları için yerleşik desteğe sahip değildi ve genellikle geliştiricilerin bu özellikleri manuel olarak uygulamalarını gerektiriyordu. Dahası, veri çekme ve bileşen render etme arasındaki sıkı bağlantı bazen performans darboğazlarına yol açabiliyordu.

App Dizini, React Sunucu Bileşenleri, Layout'lar ve diğer gelişmiş özellikler üzerine kurulu daha esnek ve güçlü bir yönlendirme sistemi sunarak bu sınırlamaları giderir. Basit bir dosyadan rotaya eşlemenin ötesine geçerek uygulama rotalarını ve layout'larını tanımlamak için daha bildirimsel (declarative) ve birleştirilebilir (composable) bir yaklaşım sunar.

App Dizini'ne Giriş: Yönlendirme için Yeni Bir Paradigma

Next.js projenizin kök dizininde, `app` klasörü içinde yer alan App Dizini, yönlendirmeye temelden farklı bir yaklaşım getirir. Dosyaları doğrudan rotalara eşlemek yerine, App Dizini, dizinlerin ve özel dosyaların yapısının uygulamanın rotalarını belirlediği bir kural tabanlı sistem kullanır.

Bu yaklaşım birçok önemli avantaj sunar:

App Dizini'nin Yönlendirme Sistemindeki Temel Kavramlar

App Dizini'nin yönlendirme sistemini etkili bir şekilde kullanmak için, işlevselliğinin temelini oluşturan anahtar kavramları anlamak çok önemlidir:

1. Rota Segmentleri ve Klasörler

`app` dizini içindeki her klasör bir rota segmentini temsil eder. Klasörün adı, URL'deki yol segmentine karşılık gelir. Örneğin, bir `app/blog/posts` klasör yapısı `/blog/posts` rotasına eşlenir.

Şu yapıyı göz önünde bulundurun:

app/
  blog/
    posts/
      page.js

Bu yapı `/blog/posts` adresinde bir rota tanımlar. `posts` klasöründeki `page.js` dosyası, o rota için içeriği render eden rota segmenti bileşenidir.

2. `page.js` Dosyası: Rota İçeriğini Render Etme

page.js (veya TypeScript için page.tsx) dosyası, belirli bir rota segmenti için render edilecek içeriği tanımlayan özel bir dosyadır. O rotanın giriş noktasıdır. Bu dosyanın, varsayılan dışa aktarım olarak bir React bileşeni ihraç etmesi gerekir.

Örnek:

// app/blog/posts/page.js

export default function PostsPage() {
  return (
    <div>
      <h1>Blog Gönderileri</h1>
      <p>Blog gönderilerinin listesi burada görüntülenecektir.</p>
    </div>
  );
}

3. Layout'lar: Paylaşılan Arayüzü Tanımlama

Layout'lar, birden çok sayfa veya rota segmenti arasında paylaşılan kullanıcı arayüzünü tanımlamanıza olanak tanır. Bir layout, başlıklar, altbilgiler, kenar çubukları veya uygulamanızın bir bölümü boyunca tutarlı olması gereken diğer bileşenleri içerebilir. Layout'lar `layout.js` (veya `layout.tsx`) dosyası kullanılarak tanımlanır.

Layout'lar iç içedir. Bu, kök layout'un (`app/layout.js`) tüm uygulamayı sarmaladığı ve iç içe geçmiş layout'ların belirli rota segmentlerini sarmaladığı anlamına gelir. Bir layout'u paylaşan rotalar arasında gezinirken, Next.js layout'un durumunu korur ve yeniden render edilmesini önler, bu da daha iyi performans ve daha akıcı bir kullanıcı deneyimi sağlar.

Örnek:

// app/layout.js

export default function RootLayout({ children }) {
  return (
    <html>
      <body>
        <header>
          <nav>
            <a href="/">Ana Sayfa</a> |
            <a href="/blog">Blog</a>
          </nav>
        </header>
        <main>{children}</main>
        <footer>
          <p>Telif Hakkı 2023</p>
        </footer>
      </body>
    </html>
  );
}

Bu örnekte, `RootLayout` tüm uygulama için temel HTML yapısını, başlığı, altbilgiyi ve gezinmeyi tanımlar. `app` dizini içinde render edilen herhangi bir sayfa bu layout tarafından sarmalanacaktır.

4. Şablonlar (Templates): Rotalar Arasında Durumu Koruma

Layout'lara benzer şekilde, şablonlar da alt rotaları sarmalar. Ancak, layout'lardan farklı olarak, şablonlar her alt rota için yeni bir bileşen örneği oluşturur. Bu, şablonun durumunun, şablon içindeki rotalar arasında gezinirken korunmadığı anlamına gelir. Şablonlar, rota geçişlerinde durumu sıfırlamanız veya yeniden başlatmanız gereken senaryolar için kullanışlıdır. Şablon oluşturmak için template.js (veya template.tsx) kullanın.

5. Rota Grupları: URL Segmentleri Olmadan Rotaları Organize Etme

Rota grupları, URL yapısını etkilemeden rotalarınızı App Dizini içinde organize etmenize olanak tanır. Rota grupları, klasör adlarını parantez içine alarak tanımlanır, örn. `(grup-adi)`. Bu parantezler Next.js'e klasörü bir rota segmenti yerine mantıksal bir gruplama mekanizması olarak ele almasını söyler.

Bu, özellikle çok sayıda rotası olan büyük uygulamaları organize etmek için kullanışlıdır. Örneğin, rota gruplarını uygulamanızın `(pazarlama)` ve `(uygulama)` gibi farklı bölümlerini ayırmak için kullanabilirsiniz. Bu gruplar yalnızca dosya yapısını etkiler, URL yollarını etkilemez.

Örnek:

app/
  (marketing)/
    home/
      page.js  // /home adresinden erişilebilir
    about/
      page.js  // /about adresinden erişilebilir
  (app)/
    dashboard/
      page.js  // /dashboard adresinden erişilebilir

6. Dinamik Rotalar: Değişken Segmentleri Yönetme

Dinamik rotalar, değişken segmentlere sahip rotalar oluşturmanıza olanak tanır. Bu, blog gönderileri, ürün sayfaları veya kullanıcı profilleri gibi verilere dayalı rotalar oluşturmanız gereken senaryolar için kullanışlıdır. Dinamik rota segmentleri, segment adını köşeli parantez içine alarak tanımlanır, örn. `[id]`. `id`, `page.js` bileşeni içinde erişilebilen bir parametreyi temsil eder.

Örnek:

app/
  blog/
    [slug]/
      page.js

Bu örnekte, `[slug]` dinamik bir rota segmentidir. `/blog/ilk-yazim` gibi bir URL bu rotayla eşleşir ve `slug` parametresi `ilk-yazim` olarak ayarlanır. `slug` parametresine `page.js` bileşeni içindeki `params` prop'u aracılığıyla erişebilirsiniz.

// app/blog/[slug]/page.js

export default function BlogPost({ params }) {
  const { slug } = params;
  return (
    <div>
      <h1>Blog Yazısı: {slug}</h1>
      <p>Şu slug'a sahip blog yazısının içeriği: {slug}</p>
    </div>
  );
}

Bu dinamik rotalar için olası değerleri oluşturmanız gerekir. Next.js, statik site oluşturma (SSG) ve sunucu tarafı render etme (SSR) için `generateStaticParams` fonksiyonunu sağlar. Bu fonksiyon, hangi dinamik rotaların derleme zamanında önceden render edilmesi gerektiğini belirtmenize olanak tanır.

// app/blog/[slug]/page.js

export async function generateStaticParams() {
  const posts = [
    { slug: 'ilk-yazim' },
    { slug: 'ikinci-yazim' },
  ];

  return posts.map((post) => ({ slug: post.slug }));
}

export default function BlogPost({ params }) {
  const { slug } = params;
  return (
    <div>
      <h1>Blog Yazısı: {slug}</h1>
      <p>Şu slug'a sahip blog yazısının içeriği: {slug}</p>
    </div>
  );
}

7. Catch-All Segmentleri: Bilinmeyen Rotaları Yönetme

Catch-all segmentleri, bir URL'deki herhangi bir sayıda segmentle eşleşmenize olanak tanıyan bir dinamik rota türüdür. Segment adının önüne üç nokta koyularak tanımlanırlar, örn. `[...path]`. Catch-all segmentleri, çeşitli URL yapılarını işleyebilen esnek rotalar oluşturmak için kullanışlıdır.

Örnek:

app/
  docs/
    [...path]/
      page.js

Bu örnekte, `[...path]` bir catch-all segmentidir. `/docs/introduction`, `/docs/api/reference` ve `/docs/examples/basic` gibi URL'lerin hepsi bu rotayla eşleşir. `path` parametresi, eşleşen segmentleri içeren bir dizi olacaktır.

// app/docs/[...path]/page.js

export default function DocsPage({ params }) {
  const { path } = params;
  return (
    <div>
      <h1>Dokümantasyon</h1>
      <p>Yol: {path.join('/')}</p>
    </div>
  );
}

8. Paralel Rotalar: Birden Çok Sayfayı Eşzamanlı Olarak Render Etme

Paralel Rotalar, aynı layout içinde birden çok sayfayı eşzamanlı olarak render etmenizi sağlar. Bu, birden çok paneli olan kontrol panelleri veya mevcut sayfanın üzerinde görünen modal diyaloglar gibi karmaşık UI desenleri oluşturmak için özellikle kullanışlıdır. Paralel rotalar @ sembolü kullanılarak tanımlanır, örn. `@children`, `@modal`. Doğrudan URL'de belirtilebilirler veya `useRouter` kancası kullanılarak gezilebilirler.

Örnek:

app/
  @children/
    page.js // Ana içeriği render eder
  @modal/
    login/
      page.js // Giriş modalını render eder

Paralel rotaları görüntülemek için `` bileşenini kullanın.

9. Rotaları Kesme (Intercepting Routes): Gelişmiş UI Geçişleri Oluşturma

Rotaları Kesme, uygulamanızın farklı bir bölümünden bir rotayı mevcut rotanın bağlamı içinde yüklemenize olanak tanır. Bu, mevcut sayfadan ayrılmadan bir bağlantıya tıklandığında modal bir diyalog görüntülemek gibi gelişmiş UI geçişleri oluşturmak için kullanılabilir. (...) sözdizimi kullanılarak tanımlanırlar.

App Dizini'nde Veri Çekme

App Dizini, React Sunucu Bileşenleri ve yerleşik önbellekleme ve yeniden doğrulama yeteneklerine sahip `fetch` API'sinden yararlanarak veri çekmek için yeni ve geliştirilmiş yollar sunar. Bu, daha iyi performansa ve daha akıcı bir geliştirme deneyimine yol açar. Hem Sunucu hem de İstemci bileşenleri veri çekebilir, ancak strateji farklıdır.

1. Sunucu Bileşenlerinde Veri Çekme

App Dizini'nde varsayılan olan Sunucu Bileşenleri, veritabanlarından veya API'lerden doğrudan veri çekebilir. Bu, render etmeden önce bileşen fonksiyonu içinde yapılır. Sunucu Bileşenleri sunucuda çalıştığı için, gizli anahtarları ve kimlik bilgilerini istemciye ifşa etmeden güvenle dahil edebilirsiniz. `fetch` API'si otomatik olarak hafızaya alınır (memoized), yani aynı veri istekleri tekilleştirilir ve performansı daha da artırır.

// app/page.js

async function getData() {
  const res = await fetch('https://jsonplaceholder.typicode.com/todos/1');
  // Dönen değer serileştirilmez
  // Date, Map, Set vb. döndürebilirsiniz.

  if (!res.ok) {
    // Bu, en yakın `error.js` Hata Sınırını (Error Boundary) etkinleştirir
    throw new Error('Veri çekme başarısız oldu');
  }

  return res.json();
}

export default async function Page() {
  const data = await getData();

  return <div>{data.title}</div>;
}

2. İstemci Bileşenlerinde Veri Çekme

Dosyanın en üstündeki 'use client' yönergesi ile belirtilen İstemci Bileşenleri, kullanıcının tarayıcısında çalışır. İstemci Bileşenlerinde veri çekme genellikle `useEffect` kancasını ve `axios` gibi bir kütüphaneyi veya `fetch` API'sini kullanmayı içerir. Sunucu Eylemleri (Server Actions), istemci bileşenlerinden sunucu verilerini güvenli bir şekilde değiştirmenin bir yolunu sunar. Bu, istemci bileşenlerinin API uç noktalarını doğrudan ifşa etmeden sunucudaki verilerle etkileşim kurması için güvenli bir yol sunar.

// app/components/ClientComponent.js
'use client';

import { useState, useEffect } from 'react';

export default function ClientComponent() {
  const [data, setData] = useState(null);

  useEffect(() => {
    async function fetchData() {
      const res = await fetch('https://jsonplaceholder.typicode.com/todos/1');
      const data = await res.json();
      setData(data);
    }

    fetchData();
  }, []);

  if (!data) {
    return <div>Yükleniyor...</div>;
  }

  return <div>{data.title}</div>;
}

App Dizini ile SEO Hususları

App Dizini'nin sunucu öncelikli yaklaşımı, SEO için önemli avantajlar sunar. İçerik sunucuda render edildiğinden, arama motoru tarayıcıları sayfa içeriğine kolayca erişebilir ve indeksleyebilir. İşte bazı önemli SEO hususları:

App Dizini'nin Yönlendirme Sistemini Kullanmanın Faydaları

App Dizini'nin yönlendirme sistemi, geliştirme sürecini geliştiren, uygulama performansını iyileştiren ve daha iyi bir kullanıcı deneyimine katkıda bulunan çok sayıda fayda sunar. Bu avantajları daha ayrıntılı olarak inceleyelim:

App Dizini Yönlendirmesinin Pratikteki Örnekleri

App Dizini'nin yönlendirme sisteminin gücünü ve esnekliğini göstermek için birkaç pratik örneği ele alalım:

1. Dinamik Rotalarla Basit Bir Blog Oluşturma

Her blog yazısının slug'ına göre kendi benzersiz URL'sine sahip olduğu bir blog uygulaması düşünün. App Dizini ile bu, dinamik rotalar kullanılarak kolayca uygulanabilir:

``` app/ blog/ [slug]/ page.js ```

`[slug]` dizini, `/blog/` yolu altındaki herhangi bir URL ile eşleşecek olan dinamik bir rota segmentini temsil eder. `[slug]` dizini içindeki `page.js` dosyası, ilgili blog yazısının içeriğini render edecektir.

```javascript // app/blog/[slug]/page.js export async function generateStaticParams() { // Veritabanından veya API'den tüm blog yazılarını çekin const posts = await fetchPosts(); // Yazıları bir slug parametreleri dizisine eşleyin return posts.map((post) => ({ slug: post.slug })); } export default async function BlogPost({ params }) { const { slug } = params; // Eşleşen slug'a sahip blog yazısını çekin const post = await fetchPost(slug); if (!post) { return <div>Yazı bulunamadı</div>; } return ( <article> <h1>{post.title}</h1> <p>{post.content}</p> </article> ); } ```

Bu örnek, her blog yazısı için ayrı sayfalar oluşturmak üzere dinamik rotaların basit ve verimli bir şekilde nasıl kullanılacağını göstermektedir.

2. Rotaları Kesme ile Modal Diyalog Uygulama

Bir kullanıcının bir bağlantıya tıkladığında, mevcut sayfadan ayrılmadan görünen bir modal diyalog uygulamak istediğinizi varsayalım. Bu, rotaları kesme (intercepting routes) kullanılarak başarılabilir:

``` app/ (.)photos/ [id]/ @modal/ page.js page.js ```

Burada, `(.)photos/[id]/@modal/page.js`, mevcut sayfadan `photos/[id]` adresine giden istekleri keser. Bir kullanıcı belirli bir fotoğrafın bağlantısına tıkladığında, yeni bir sayfaya gitmek yerine modal diyalog mevcut sayfanın üzerinde görünecektir.

3. Paralel Rotalarla Bir Kontrol Paneli Düzeni Oluşturma

Aynı anda render edilmesi gereken birden çok paneli olan bir kontrol paneli uygulaması oluşturduğunuzu hayal edin. Bu düzeni elde etmek için paralel rotalar kullanılabilir:

``` app/ @analytics/ page.js // Analitik Kontrol Paneli @settings/ page.js // Ayarlar Paneli page.js // Ana Kontrol Paneli Düzeni ```

Bu yapıda, `@analytics` ve `@settings`, ana kontrol paneli düzeni içinde render edilecek paralel rotaları temsil eder. Her paralel rotanın, o panelin içeriğini tanımlayan kendi page.js dosyası vardır. Layout, <Slot> bileşenini kullanarak bunları nereye yerleştireceğine karar verebilir.

Pages Dizini'nden App Dizini'ne Geçiş

Mevcut bir Next.js uygulamasını Pages Dizini'nden App Dizini'ne taşımak dikkatli bir planlama ve uygulama gerektirir. App Dizini önemli avantajlar sunsa da, geliştiricilerin anlaması gereken yeni kavramlar ve kalıplar da getirir. İşte geçiş sürecinde size yardımcı olacak adım adım bir kılavuz:

  1. Temel Farklılıkları Anlayın: Geçişe başlamadan önce, Pages Dizini ile App Dizini arasındaki yönlendirme sistemi, veri çekme ve bileşen mimarisi dahil olmak üzere temel farklılıkları tam olarak anladığınızdan emin olun.
  2. Bir `app` Dizini Oluşturun: Next.js projenizin kökünde `app` adında yeni bir dizin oluşturun. Bu dizin, App Dizini'nin bir parçası olan tüm bileşenleri ve rotaları barındıracaktır.
  3. Rotaları Aşamalı Olarak Taşıyın: Rotaları tek tek, aşamalı olarak taşımaya başlayın. Bu, her rotayı ayrı ayrı test etmenize ve hata ayıklamanıza olanak tanıyarak hata yapma riskini en aza indirir.
  4. Bileşenleri Sunucu Bileşenlerine Dönüştürün: Mevcut React bileşenlerinizi mümkün olduğunca Sunucu Bileşenlerine dönüştürün. Bu, performansı artıracak ve tarayıcıda indirilip çalıştırılması gereken JavaScript miktarını azaltacaktır.
  5. Veri Çekme Mantığını Güncelleyin: Veri çekme mantığınızı, App Dizini'nin yerleşik veri çekme yeteneklerinden yararlanacak şekilde güncelleyin. Bu, veri çekme kodunu İstemci Bileşenlerinden Sunucu Bileşenlerine taşımayı içerebilir.
  6. Layout'lar ve Şablonlar Uygulayın: Birden çok sayfada tutarlı olan paylaşılan UI öğelerini tanımlamak için layout'lar ve şablonlar uygulayın.
  7. Kapsamlı Test Edin: Taşınan her rotanın doğru çalıştığından ve herhangi bir gerileme olmadığından emin olmak için kapsamlı bir şekilde test edin.
  8. `pages` dizinini kaldırın: Tüm rotalar taşındıktan sonra, `/pages` dizinini kaldırabilirsiniz.

Sonuç

Next.js App Dizini, dosya tabanlı yönlendirmede önemli bir evrimi temsil ederek geliştiricilere modern web uygulamaları oluşturmak için daha organize, performanslı ve esnek bir yol sunar. Temel kavramları anlayarak ve yeni özellikleri benimseyerek, geliştiriciler olağanüstü kullanıcı deneyimleri yaratmak ve daha yüksek verimlilik elde etmek için App Dizini'nden yararlanabilirler. Next.js geliştirmenin geleceği App Dizini'nde yatmaktadır ve onu benimsemek, en son teknolojiye sahip web uygulamaları oluşturmak için stratejik bir harekettir. Dünya çapındaki geliştiriciler için güçlü bir araçtır.

Next.js ekosistemi gelişmeye devam ettikçe, App Dizini sağlam, ölçeklenebilir ve performanslı web uygulamaları oluşturmak için standart haline gelmeye hazırlanıyor. Değişimi kucaklayın, olasılıkları keşfedin ve Next.js'in tüm potansiyelini ortaya çıkarın!