İçeriğe geç

Next.js ile Kullanım

Next.js, projenin kök dizininde (root) veya src klasöründe özel app veya pages klasörlerinin bulunmasını bekler. Genellikle, Next.js klasörlerini projenin kök dizinine yerleştirmek, src klasörünün yalnızca FSD kodunu içermesini sağladığı için daha kolaydır; ancak bu zorunlu değildir.

Next.js, App Router için app klasörünü ve Pages Router için pages klasörünü kullanır; bu durum FSD katman adlarıyla çakışır. Bu çakışmayı çözmek için, app yerine _app ve pages yerine _pages gibi FSD katmanları için ön ek (prefix) içeren adlar kullanın. Bu yaklaşım resmi linter ile de uyumludur.

  • Dizinapp Next.js app klasörü
    • Dizinapi/
      • Dizinget-example/
        • route.ts
    • Dizinexample/
      • page.tsx
  • Dizinsrc/
    • Dizin_app/ FSD katmanı
      • Dizinapi-routes/ API rotaları
    • Dizin_pages/ FSD katmanı
      • Dizinexample/
        • index.ts
        • Dizinui/
          • example.tsx
    • Dizinwidgets/
    • Dizinfeatures/
    • Dizinentities/
    • Dizinshared/

Next.js app içinde src/_pages katmanından bir sayfanın yeniden dışa aktarılması (re-export) örneği:

app/example/page.tsx
export { ExamplePage as default, metadata } from '@/_pages/example';

Next.js App Router’da, istemcide kullanılabilecek modüller ve yalnızca sunucuya özel (server-only) modüller tek bir dilim (slice) içinde birlikte bulunabilir. Yalnızca sunucuya özel bir modül index.ts dosyasından dışa aktarılırsa, bir İstemci Bileşeni (Client Component) o dilimi içe aktardığında yalnızca sunucuya özel yan etkiler istemci modül grafiğine yayılabilir ve bu da derleme (build) hatalarına yol açabilir.

Bu sorun ortaya çıktığında, public API’ye index.server.ts ekleyin.

  • index.server.ts: Sunucu Bileşenleri (Server Components) veya server-only ile işaretlenmiş veri erişim fonksiyonları gibi yalnızca sunucuda içe aktarılması gereken modüller.

Projenizde middleware kullanıyorsanız, Next.js app ve pages klasörlerinin yanı sıra projenin kök dizininde yer almalıdır.

instrumentation.js dosyası, uygulamanızın performansını ve davranışını izlemenizi sağlar. Eğer kullanıyorsanız, middleware.js dosyasına benzer şekilde projenin kök dizininde bulunmalıdır.

pages katmanında FSD ve Next.js arasındaki çakışma

Section titled “pages katmanında FSD ve Next.js arasındaki çakışma”

Rotalar, App Router için app klasörüne benzer şekilde projenin kök dizinindeki pages klasörüne yerleştirilmelidir. Katman klasörlerinin bulunduğu src içindeki yapı değişmeden kalır.

  • Dizinpages/ Pages klasörü (Next.js)
    • _app.tsx
    • Dizinapi/
      • example.ts API rotası yeniden dışa aktarımı
    • Dizinexample/
      • index.tsx
  • Dizinsrc/
    • Dizin_app/ FSD katmanı
      • Dizincustom-app/
        • custom-app.tsx Özel App bileşeni
      • Dizinapi-routes/
        • get-example-data.ts API rotası
    • Dizin_pages/ FSD katmanı
      • Dizinexample/
        • index.ts
        • Dizinui/
          • example.tsx
    • Dizinwidgets/
    • Dizinfeatures/
    • Dizinentities/
    • Dizinshared/

Next.js pages içinde src/_pages katmanından bir sayfanın yeniden dışa aktarılması örneği:

pages/example/index.tsx
export { Example as default } from '@/_pages/example';

Özel App bileşeninizi src/_app/_app veya src/_app/custom-app içine yerleştirebilirsiniz:

src/_app/custom-app/custom-app.tsx
import type { AppProps } from 'next/app';
export const MyApp = ({ Component, pageProps }: AppProps) => {
return (
<>
<p>My Custom App component</p>
<Component { ...pageProps } />
</>
);
};
pages/_app.tsx
export { App as default } from '@/_app/custom-app';

Rota İşleyicileri (Route Handlers) ile çalışmak için _app katmanındaki api-routes segmentini kullanın.

FSD yapısında backend kodu yazarken dikkatli olun — FSD öncelikle frontend için tasarlanmıştır, yani insanların bulmayı bekleyeceği şey budur. Çok sayıda endpoint’e ihtiyacınız varsa, bunları bir monorepo içinde farklı bir pakete ayırmayı düşünün.

src/_app/api-routes/get-example-data.ts
import { getExamplesList } from '@/shared/db';
export const getExampleData = () => {
try {
const examplesList = getExamplesList();
return Response.json({ examplesList });
} catch {
return Response.json(null, {
status: 500,
statusText: 'Ouch, something went wrong',
});
}
};
app/api/example/route.ts
export { getExampleData as GET } from '@/_app/api-routes';
  • Veritabanı sorgularını ve bunların üst katmanlardaki sonraki kullanımlarını tanımlamak için shared katmanındaki db segmentini kullanın.
  • Sorguları önbelleğe alma (caching) ve yeniden doğrulama (revalidating) mantığını, sorguların kendisiyle aynı yerde tutmak daha iyidir.