Next.js ile Modern Web Geliştirme: Kapsamlı Rehber

1. Next.js Nedir ve Neden Tercih Edilir
Next.js, React tabanlı, üretime hazır bir web framework'üdür. Vercel tarafından geliştirilen bu araç, geliştiricilere sunucu tarafı render etme, statik site oluşturma ve API rotaları gibi güçlü özellikler sunar. 2026 itibarıyla Next.js 15, React Server Components (RSC) mimarisi, Turbopack derleyicisi ve App Router ile modern web geliştirmenin altın standardı haline gelmiştir.
Peki neden Next.js? Geleneksel React uygulamalarında karşılaşılan SEO zorlukları, ilk sayfa yüklenme süreleri ve yapılandırma karmaşası, Next.js ile tarihe karışıyor. Framework, dosya tabanlı routing, otomatik kod bölme ve görsel optimizasyon gibi konuları varsayılan olarak çözüyor. Özellikle e-ticaret, SaaS ve kurumsal projelerde performans optimizasyonu kritik öneme sahip; Next.js'in sunduğu esnek render stratejileri bu noktada devreye giriyor.
Profesyonel ekiplerde tercih sebebi olan bir diğer unsur, ekosistem bütünlüğüdür. TypeScript, Tailwind CSS, ESLint ve daha fazlası tek bir komutla yapılandırılabiliyor. Agile süreçlerde hızlı iterasyon yapabilen ekipler için bu, teknik borç riskini azaltıyor. Ayrıca Vercel platformu ile sıfır yapılandırmalı dağıtım imkanı, CI/CD entegrasyonlarını kolaylaştırıyor. Sonuç olarak, Next.js sadece bir kütüphane değil; modern web geliştirme için kapsamlı bir çözüm ortağıdır.
// next.config.ts - TypeScript destekli yapılandırma
import type { NextConfig } from 'next';
const nextConfig: NextConfig = {
experimental: {
ppr: true, // Partial Prerendering
},
};
export default nextConfig;
2. Temel Özellikler ve Render Stratejileri
Next.js 15'in en belirgin yeniliği, render stratejilerinde sunduğu çeşitlilik ve kontroldür. React Server Components (RSC) artık varsayılan davranıştır; bu sayede bileşenler sunucuda çalışır ve tarayıcıya JavaScript gönderilmez. Bu mimari, özellikle içerik ağırlıklı sayfalarda kullanıcı deneyimini doğrudan iyileştirir çünkü ilk boyama süresi (FCP) dramatik şekilde düşer.
Framework üç temel render stratejisi sunar: Static Site Generation (SSG), Server-side Rendering (SSR) ve Incremental Static Regeneration (ISR). 2026'da Partial Prerendering (PPR) de bu listeye eklendi; statik kabuk anında yüklenirken dinamik içerik stream edilir. Bu, özellikle kişiselleştirilmiş sayfalarda hem hız hem de dinamiklik sağlar. Turbopack ise geliştirme sunucusunu 10 kata kadar hızlandırarak, büyük kod tabanlarında bile anlık hot reload deneyimi sunar.
Bir diğer kritik özellik, Server Actions'tır. Artık form gönderimleri ve veri mutasyonları için ayrı API endpointleri yazmaya gerek kalmaz. Sunucu tarafında çalışan async fonksiyonlar, doğrudan bileşenlerden çağrılabilir. Bu yaklaşım, API tasarımını basitleştirir ve güvenlik açısından istemci tarafında hassas mantığı saklamanıza gerek kalmaz. Özellikle cross-platform projelerde tutarlı backend mantığı kurmak için idealdir.
// Server Action örneği - 'use server' ile sunucu tarafında çalışır
'use server';
import { revalidatePath } from 'next/cache';
export async function updateProfile(formData: FormData) {
const name = formData.get('name') as string;
// Veritabanı güncelleme işlemi
revalidatePath('/profile');
}
2.1. Server-side Rendering (SSR) Nedir ve Nasıl Kullanılır
Server-side Rendering, her istekte sayfanın sunucuda sıfırdan oluşturulması anlamına gelir. Next.js App Router'da bu, varsayılan Server Components kullanılarak otomatik gerçekleşir. Bir sayfa bileşeni async olarak tanımlandığında, veri çekme işlemleri sunucuda await edilir ve HTML istemciye hazır halde ulaşır. Bu yaklaşım, sürekli değişen verilerin gösterildiği sayfalar için idealdir.
SSR'nin en büyük avantajı, her kullanıcıya güncel içerik sunabilmesidir. Örneğin bir finans dashboard'u veya canlı spor skorları sayfası düşünün; bu senaryolarda statik önbellek kullanmak mantıklı değildir. Next.js 15'te fetch çağrılarında cache: 'no-store' seçeneği ile SSR davranışı zorlanabilir. Ayrıca cookies() ve headers() gibi sunucu API'leri sayesinde, istek başına kişiselleştirme yapılabilir.
Ancak SSR'nin maliyeti de vardır. Her istekte sunucu kaynağı tüketilir ve Time to First Byte (TTFB) değeri SSG'ye göre yüksek olabilir. Bu nedenle profesyonel ekiplerde, hangi sayfaların SSR, hangilerinin SSG/ISR olacağına proje başında karar verilir. Özellikle e-ticaret sitelerinde ürün detay sayfaları ISR ile önbelleklenirken, kullanıcı sepeti ve ödeme sayfaları SSR ile dinamik tutulur.
// SSR örneği - Her istekte güncel veri
export default async function LiveDashboard() {
const data = await fetch('https://api.example.com/live-data', {
cache: 'no-store', // SSR: önbelleklenmez
});
const metrics = await data.json();
return <Dashboard metrics={metrics} />;
}
2.2. Static Site Generation (SSG) ve Incremental Static Regeneration (ISR) Örnekleri
Static Site Generation, yapı zamanında (build time) sayfaların HTML olarak oluşturulmasıdır. Next.js App Router'da fetch çağrıları varsayılan olarak önbelleğe alınır ve sayfalar statik olarak render edilir. Bu, blog yazıları, pazarlama sayfaları ve dokümantasyon gibi nadiren değişen içerikler için mükemmel bir performans optimizasyonu sağlar.
ISR ise SSG'nin dinamik halidir. Sayfa statik olarak oluşturulur, ancak belirli bir süre sonra arka planda yeniden oluşturulur. revalidate: 3600 gibi bir parametre ile sayfa her saat başı güncellenir. Bu, milyonlarca ürünün olduğu e-ticaret sitelerinde hayat kurtarır; her ürün için sunucu kaynağı harcamadan, yine de fiyat stok bilgileri güncel kalır.
2026'da Partial Prerendering (PPR) bu iki dünyayı birleştirir. Sayfanın statik kısımları anında gösterilirken, dinamik kısımlar (örneğin kişiselleştirilmiş öneriler) stream edilir. Bu karma strateji, özellikle SaaS uygulamalarında hem hızlı ilk yükleme hem de zengin interaktivite sunar.
// ISR örneği - Saatlik yenileme
export default async function ProductPage() {
const products = await fetch('https://api.example.com/products', {
next: { revalidate: 3600 }, // 1 saatte bir yeniden oluştur
});
return <ProductList products={products} />;
}
2.3. Edge Functions Avantajları ve Kullanım Senaryoları
Edge Functions, kodunuzu CDN düğümlerine (edge nodes) yakın konumlarda çalıştırmanızı sağlar. Next.js 15'te middleware ve route handlers edge runtime'da çalışabilir. Bu, coğrafi olarak dağıtılmış kullanıcılara düşük gecikme süreleriyle yanıt vermek için kritik öneme sahiptir.
Edge Functions'ın en belirgin avantajı, global dağıtımdır. Bir kullanıcı Tokyo'dan istek yaptığında, kod San Francisco'daki origin sunucusuna gitmek yerine Tokyo'daki edge düğümünde çalışır. Bu, özellikle oturum kontrolü, A/B testleri ve coğrafi yönlendirme gibi işlemlerde milisaniyeler kazandırır. Ancak edge ortamında Node.js API'lerinin tamamı mevcut değildir; bu nedenle veritabanı bağlantıları gibi ağır işlemler için dikkatli kullanılmalıdır.
Profesyonel ekiplerde edge kullanımı, kullanıcı deneyimini optimize etmenin en etkili yollarından biridir. Özellikle mobil uygulama arka uçlarında, düşük gecikme kullanıcı memnuniyetini doğrudan etkiler. Ayrıca edge'de çalışan middleware ile güvenlik kuralları, rate limiting ve bot koruması gibi işlemler origin sunucuyu yormadan gerçekleştirilebilir.
// Edge Middleware örneği
export const config = {
runtime: 'edge',
};
export default async function handler(req: Request) {
const country = req.geo?.country;
return new Response(`Merhaba ${country}!`);
}
3. Görsel Sayfa Oluşturma ve Image Component Nasıl Kullanılır (Responsive Tasarım)
Modern web'de görseller, sayfa boyutunun büyük kısmını oluşturur ve kullanıcı deneyimini doğrudan etkiler. Next.js, next/image bileşeni ile bu sorunu kökten çözer. Otomatik format dönüşümü (WebP/AVIF), boyutlandırma ve lazy loading özellikleri sayesinde, manuel optimizasyon ihtiyacını ortadan kaldırır.
Responsive tasarımda next/image kullanımı oldukça sezgiseldir. sizes prop'u ile farklı ekran genişliklerinde hangi boyutların yükleneceği belirtilir. Bu, özellikle mobil uygulama benzeri web deneyimleri sunarken, bant genişliğini verimli kullanmak için kritiktir. Görsel, ekran boyutuna göre otomatik olarak küçültülür ve uygun srcset oluşturulur.
Next.js 15'te görsel optimizasyonu, edge'de gerçekleşir. İlk istekte görsel optimize edilir ve sonraki isteklerde CDN'den sunulur. Bu, özellikle medya ağırlıklı e-ticaret sitelerinde, ürün görsellerinin hızlı yüklenmesini sağlar. Ayrıca placeholder ve blur-up efektleri ile görsel yüklenene kadar kullanıcıya geri bildirim sunulur.
// Responsive görsel kullanımı
import Image from 'next/image';
export default function Hero() {
return (
<Image
src="/hero.jpg"
alt="Hero görseli"
fill
sizes="(max-width: 768px) 100vw, 50vw"
priority
className="object-cover"
/>
);
}
3.1. next/image ile Responsive Görüntü Optimizasyonu Nasıl Yapılır
Responsive görüntü optimizasyonu, farklı cihazlarda doğru boyutta ve formatta görsel sunmayı ifade eder. Next.js next/image bileşeni, bu konuda kapsamlı bir çözüm sunar. sizes prop'u ile breakpoint'ler tanımlanırken, fill modu ile parent container'a göre boyutlandırma yapılır.
Önemli bir detay, aspect ratio'nun korunmasıdır. Next.js, görselin orijinal boyutlarını bilir ve layout shift'i (CLS) önlemek için otomatik olarak yer ayırır. Bu, Core Web Vitals skorlarını iyileştirmede kritik rol oynar. Özellikle responsive tasarım hedefleyen projelerde, manuel width/height hesaplamalarına gerek kalmaz.
Profesyonel ekiplerde, görseller için bir CDN stratejisi belirlenir. Next.js, varsayılan olarak Vercel'in global CDN'ini kullanır ancak AWS CloudFront veya Cloudflare gibi alternatifler de yapılandırılabilir. Performans optimizasyonu açısından, tüm ürün görsellerinin otomatik WebP dönüşümü ve lazy loading ile sunulması, sayfa hızını dramatik şekilde artırır.
// E-ticaret ürün kartı - otomatik optimizasyon
import Image from 'next/image';
export function ProductCard({ product }) {
return (
<div className="relative aspect-square">
<Image
src={product.image}
alt={product.name}
fill
sizes="(max-width: 640px) 50vw, 25vw"
className="rounded-lg object-cover"
/>
</div>
);
}
3.2. CSS Modules, Tailwind ve Stil Stratejileri Örnekleri
Next.js, stil konusunda esnekliğiyle öne çıkar. CSS Modules, dosya bazlı scoped stil sunar; bu, büyük projelerde çakışma riskini ortadan kaldırır. Tailwind CSS ise utility-first yaklaşımıyla hızlı prototipleme ve tutarlı tasarım sistemleri kurmayı mümkün kılar.
2026'da Tailwind v4, Next.js projelerinde varsayılan olarak tercih edilir. @tailwind direktifleri globals.css içinde tanımlanır ve PostCSS entegrasyonu otomatik gerçekleşir. Bu, özellikle agile ekiplerde hızlı iterasyon yapmayı kolaylaştırır; bir bileşenin stilini değiştirmek için ayrı bir CSS dosyası açmaya gerek kalmaz.
CSS Modules ise, daha geleneksel veya karmaşık animasyon gerektiren senaryolarda tercih edilir. [name].module.css dosyaları otomatik olarak scoped class'lar üretir. Profesyonel ekiplerde, genellikle iki yaklaşım birlikte kullanılır: Tailwind genel layout ve utility'ler için, CSS Modules ise spesifik bileşen varyasyonları için.
/* globals.css - Tailwind entegrasyonu */
@tailwind base;
@tailwind components;
@tailwind utilities;
@layer components {
.btn-primary {
@apply px-4 py-2 bg-blue-600 text-white rounded-lg hover:bg-blue-700;
}
}
3.3. Dinamik Görsel Yükleme ve Lazy-Loading Uygulama Örnekleri
Dinamik görsel yükleme, sayfa yüklendikten sonra kullanıcı etkileşimine veya scroll pozisyonuna bağlı olarak görsellerin getirilmesidir. Next.js'te next/image otomatik olarak lazy loading uygular; loading="lazy" varsayılan davranıştır. Ancak dinamik import senaryolarında next/dynamic kullanımı gerekir.
Özellikle galeri, portföy veya e-ticaret ürün listeleme sayfalarında, tüm görsellerin aynı anda yüklenmesi performansı olumsuz etkiler. Intersection Observer API ile custom lazy loading uygulanabilir ancak Next.js bu işlemi native olarak halleder. priority prop'u ile kritik görseller (örneğin hero banner) öncelikli yüklenir, geri kalanı scroll ile gelir.
Dinamik import ile görsel bileşenleri, gerçekten ihtiyaç duyulduğunda yüklenir. Bu, başlangıç bundle boyutunu küçültür ve Time to Interactive (TTI) metriğini iyileştirir. Profesyonel ekiplerde, özellikle medya ağırlıklı sayfalarda bu strateji performans optimizasyonunun temel taşlarından biridir.
// Dinamik görsel bileşeni
import dynamic from 'next/dynamic';
const DynamicGallery = dynamic(() => import('@/components/Gallery'), {
loading: () => <p>Yükleniyor...</p>,
ssr: false, // İstemci tarafında yükle
});
export default function Page() {
return <DynamicGallery images={imageList} />;
}
4. Dosya Tabanlı Routing ve Layout Sistemi Nasıl Kullanılır (Web Geliştirme)
Next.js'in en tanınmış özelliklerinden biri, dosya sistemini URL yapısına doğrudan eşleyen routing mekanizmasıdır. App Router (app/ dizini), 2026 itibarıyla yeni projeler için varsayılan ve önerilen yöntemdir. Her klasör bir route segment'i, her page.tsx dosyası o segment'in UI'ını temsil eder.
Layout sistemi, App Router'ın en güçlü yanlarından biridir. layout.tsx dosyaları, alt rotalar arasında kalıcıdır ve navigasyon sırasında yeniden mount edilmezler. Bu, paylaşılan header, sidebar veya navigasyonun gereksiz yeniden render'ını önler. Özellikle SaaS dashboard'larında, kullanıcı sayfalar arasında gezerken sidebar'ın sabit kalması kritik bir kullanıcı deneyimi avantajıdır.
Dosya tabanlı routing, konvansiyon üzerine kuruludur ve bu da öğrenme eğrisini düşürür. loading.tsx ile anlık yükleme durumları, error.tsx ile hata sınırları, not-found.tsx ile 404 sayfaları otomatik olarak tanımlanır. Bu konvansiyonlar, test edilebilirlik ve bakımı kolaylaştırır çünkü her rotanın davranışı dosya yapısından anlaşılır.
// app/dashboard/layout.tsx - Nested layout
export default function DashboardLayout({
children,
}: {
children: React.ReactNode;
}) {
return (
<div className="flex">
<Sidebar />
<main className="flex-1">{children}</main>
</div>
);
}
4.1. App Router Nedir, Nasıl Yapılandırılır ve Örnekleri
App Router, Next.js 13 ile tanıtılan ve 15'te olgunlaşan modern routing sistemidir. React Server Components üzerine kuruludur ve app/ dizinini kullanır. Her klasör bir URL segment'i olur; örneğin app/blog/[slug]/page.tsx, /blog/hello-world URL'sini karşılar.
Yapılandırma neredeyse sıfırdır. create-next-app ile proje oluşturulurken --app flag'i otomatik olarak App Router'ı seçer. Mevcut Pages Router projeleri, app/ dizini oluşturularak aşamalı olarak geçiş yapabilir; her iki sistem aynı anda çalışabilir. Bu, büyük e-ticaret veya kurumsal projelerin riskli bir rewrite yerine evrimsel geçiş yapmasını sağlar.
App Router'ın en önemli felsefesi, "sunucu varsayılandır" (server-first) yaklaşımıdır. Bileşenler varsayılan olarak sunucuda çalışır ve 'use client' direktifi eklenmedikçe istemci JavaScript'i gönderilmez. Bu, özellikle içerik sitelerinde bundle boyutunu %90'a varan oranlarda düşürebilir.
// app/blog/[slug]/page.tsx - Dinamik route
export default async function BlogPost({
params,
}: {
params: { slug: string };
}) {
const post = await fetch(`https://api.example.com/posts/${params.slug}`);
const data = await post.json();
return (
<article>
<h1>{data.title}</h1>
<div dangerouslySetInnerHTML={{ __html: data.content }} />
</article>
);
}
4.2. Nested Layout ve Shared Component Kullanımı Nasıl Yapılır
Nested Layout (iç içe layout), App Router'ın mimari avantajlarından biridir. Bir layout.tsx dosyası, o dizindeki tüm alt rotaları ve onların alt rotalarını sarar. Bu layout, navigasyon sırasında korunur ve state'ini kaybetmez. Örneğin app/dashboard/layout.tsx, /dashboard/settings ve /dashboard/analytics sayfalarında ortak sidebar'ı sağlar.
Shared component kullanımı, bu mimarinin doğal uzantısıdır. Layout içinde tanımlanan bir sidebar veya header, alt sayfalara prop drilling olmadan ulaşır. Ancak dikkat edilmesi gereken nokta, client component sınırlarıdır. Bir layout sunucu bileşeni ise, içinde doğrudan client hook kullanılamaz. Bu durumda, interaktif kısımlar küçük client bileşenlere ayrılır ve server layout içinde children olarak geçirilir.
Profesyonel ekiplerde, bu pattern ile tutarlı bir UI/UX mimarisi kurulur. Özellikle SaaS uygulamalarında, her sayfanın ortak navigation, breadcrumb ve footer ile sarılması, kullanıcıların orientasyonunu korur. Ayrıca bu yapı, test edilebilirlik açısından da avantajlıdır; layout ve sayfa bileşenleri bağımsız olarak test edilebilir.
// app/dashboard/settings/layout.tsx
export default function SettingsLayout({
children,
}: {
children: React.ReactNode;
}) {
return (
<div className="settings-container">
<SettingsNav />
<div className="settings-content">{children}</div>
</div>
);
}
4.3. Dinamik Rotalar ve Parametre Yönetimi Örnekleri
Dinamik rotalar, köşeli parantez [param] sözdizimi ile tanımlanır. app/products/[id]/page.tsx, /products/123 gibi URL'leri yakalar. Parametreler, bileşen props'u olarak params nesnesi içinde ulaşılır. TypeScript ile tip güvenliği sağlamak için params tipi açıkça tanımlanmalıdır.
Çok seviyeli dinamik rotalar da mümkündür. app/shop/[category]/[productId]/page.tsx gibi bir yapı, hem kategori hem ürün ID'sini parametre olarak alır. Bu, özellikle e-ticaret sitelerinde SEO dostu URL yapıları kurmak için idealdir. Ayrıca generateStaticParams fonksiyonu ile build zamanında hangi dinamik rotaların önceden oluşturulacağı belirtilebilir.
Parametre yönetiminde dikkat edilmesi gereken bir diğer konu, parallel routes ve intercepting routes'tur. @folder sözdizimi ile aynı layout içinde birden fazla sayfa paralel olarak render edilebilir. Bu, dashboard gibi karmaşık arayüzlerde, ana içerik ve yan panelin aynı anda yönetilmesini sağlar.
// app/products/[id]/page.tsx - Tip güvenli dinamik route
interface PageProps {
params: { id: string };
}
export default async function ProductPage({ params }: PageProps) {
const product = await fetch(`https://api.example.com/products/${params.id}`);
const data = await product.json();
return <ProductDetail product={data} />;
}
// Statik parametreler üretimi
export async function generateStaticParams() {
const products = await fetch('https://api.example.com/products');
const data = await products.json();
return data.map((p: { id: string }) => ({ id: p.id }));
}
5. API Routes, Middleware ve Edge Functions Nasıl Kullanılır
Next.js, frontend'in yanı sıra backend yetenekleri de sunar. app/api/ dizinindeki route.ts dosyaları, RESTful endpoint'ler oluşturmanıza olanak tanır. Bu, ayrı bir backend sunucusu kurmadan, full-stack uygulamalar geliştirmek için idealdir. Özellikle prototipleme aşamasında veya agile süreçlerde hızlı MVP çıkarmak için değerlidir.
Middleware, isteklerin uygulamaya ulaşmadan önce işlenmesini sağlar. middleware.ts dosyası, edge runtime'da çalışır ve global yönlendirme, kimlik doğrulama kontrolü veya bot koruması gibi işlemler için kullanılır. Edge'de çalışması, düşük gecikme ve global ölçeklenebilirlik avantajı sunar.
Edge Functions ise, API route'ların edge runtime'da çalışan versiyonlarıdır. export const runtime = 'edge' ile bir route edge'de çalıştırılabilir. Bu, özellikle coğrafi konum bazlı içerik sunumu, hafif transformasyon işlemleri veya hızlı cache kontrolü için uygundur. Ancak ağır veritabanı işlemleri için Node.js runtime tercih edilmelidir.
// app/api/webhook/route.ts - API Route
import { NextResponse } from 'next/server';
export async function POST(request: Request) {
const body = await request.json();
// Webhook işleme mantığı
return NextResponse.json({ received: true });
}
5.1. API Routes Nedir, Nasıl Yazılır ve Örnekleri
API Routes, Next.js uygulamanızın içinde REST endpoint'leri tanımlamanızı sağlar. App Router'da app/api/path/route.ts konvansiyonu kullanılır. HTTP metotları (GET, POST, PUT, DELETE) ayrı export'lar olarak tanımlanır. Bu, frontend ve backend kodunun aynı repo ve hatta aynı framework içinde yaşamasını sağlar.
TypeScript desteği sayesinde, request ve response tipleri güvenli hale getirilebilir. NextRequest ve NextResponse tipleri, Next.js'in sunduğu ek özelliklere (örneğin cookie yönetimi) erişim sağlar. Profesyonel ekiplerde, bu yapı ile API versiyonlama ve tutarlı hata formatları kolayca uygulanır.
Server Actions'ın yaygınlaşmasıyla API Routes kullanımı azalmış olsa da, harici sistemlerin webhook çağrıları yapması veya üçüncü taraf entegrasyonları için hala vazgeçilmezdir. Örneğin bir ödeme sağlayıcısı webhook'u veya mobil uygulamanızın kullandığı REST endpoint için API Routes kullanılır.
// app/api/users/route.ts - CRUD örneği
import { NextResponse } from 'next/server';
export async function GET() {
const users = await db.user.findMany();
return NextResponse.json(users);
}
export async function POST(request: Request) {
const body = await request.json();
const user = await db.user.create({ data: body });
return NextResponse.json(user, { status: 201 });
}
5.2. Middleware ile İstek Ön İşleme ve Yönlendirme Nasıl Yapılır
Middleware, middleware.ts dosyası ile kök dizinde tanımlanır ve belirli path'ler için çalışır. matcher konfigürasyonu ile hangi rotaların middleware'den geçeceği kontrol edilir. Bu, uygulamanın geri kalanına ulaşmadan önce kimlik doğrulama, coğrafi yönlendirme veya A/B test grupları belirleme için kullanılır.
Yönlendirme (rewrite ve redirect) middleware'in en yaygın kullanım alanlarındandır. Örneğin eski bir URL yapısından yenisine yönlendirme, veya dil bazlı routing (/tr/, /en/) burada yönetilebilir. NextResponse.rewrite() ile kullanıcı farklı bir URL görmeksizin içerik değiştirilebilir; bu, özellikle e-ticaret sitelerinde kampanya sayfaları için kullanışlıdır.
Profesyonel ekiplerde, middleware ayrıca güvenlik katmanı olarak görev alır. JWT token kontrolü, IP bazlı kısıtlamalar veya bot tespiti burada yapılabilir. Edge'de çalışması, bu kontrollerin kullanıcıya yakın konumlarda ve düşük gecikmeyle gerçekleşmesini sağlar.
// middleware.ts - Kimlik doğrulama ve yönlendirme
import { NextResponse } from 'next/server';
import type { NextRequest } from 'next/server';
export function middleware(request: NextRequest) {
const token = request.cookies.get('auth-token');
const isAuthPage = request.nextUrl.pathname.startsWith('/login');
if (!token && !isAuthPage) {
return NextResponse.redirect(new URL('/login', request.url));
}
return NextResponse.next();
}
export const config = {
matcher: ['/dashboard/:path*', '/profile/:path*'],
};
5.3. Edge Functions ile Düşük Gecikme Senaryoları Nasıl Uygulanır
Edge Functions, kodunuzu kullanıcıya coğrafi olarak en yakın veri merkezinde çalıştırır. Next.js'te export const runtime = 'edge' ile bir API route veya middleware edge ortamına taşınabilir. Bu, özellikle global kullanıcı kitlesine sahip SaaS uygulamalarında, API yanıt sürelerini milisaniyeler içinde tutmak için kritiktir.
Düşük gecikme senaryoları arasında, coğrafi konum bazlı içerik (fiyatlandırma, dil), hafif transformasyonlar (JSON manipülasyonu, header ekleme) ve cache kontrolü öne çıkar. Örneğin bir haber sitesi, edge'de çalışan bir fonksiyon ile kullanıcının ülkesine göre farklı başlık gösterebilir. Ancak edge ortamında Node.js API'leri (fs, crypto'nun bazı fonksiyonları) sınırlıdır; bu nedenle ağır işlemler origin'e bırakılmalıdır.
Profesyonel ekiplerde, edge kullanımı performans optimizasyonu stratejisinin bir parçasıdır. Vercel Analytics veya Lighthouse ile ölçülen metrikler, edge fonksiyonlarının etkisini somut olarak gösterir. Özellikle mobil uygulama kullanıcıları için, her milisaniyelik gecikme kullanıcı memnuniyetini etkiler.
// app/api/edge/route.ts - Edge function
export const runtime = 'edge';
export async function GET(request: Request) {
const country = request.headers.get('cf-ipcountry') || 'TR';
const pricing = getPricingForCountry(country);
return new Response(JSON.stringify(pricing), {
headers: { 'content-type': 'application/json' },
});
}
5.3.1. Güvenlik Header'ları ve Rate Limiting Middleware Teknik Detayları
Güvenlik header'ları, XSS, clickjacking ve MIME sniffing gibi saldırıları önler. Next.js'te next.config.ts içinde headers() fonksiyonu ile global header'lar tanımlanabilir. Content-Security-Policy (CSP), X-Frame-Options, X-Content-Type-Options gibi header'lar, uygulamanın güvenlik duruşunu güçlendirir.
Rate limiting, kötüye kullanımı önlemek için istek sayısını sınırlar. Edge middleware'de basit bir in-memory rate limiting uygulanabilir ancak üretimde Redis veya Vercel KV gibi dağıtık çözümler tercih edilir. Özellikle API endpoint'lerinde ve oturum açma sayfalarında rate limiting, brute-force saldırılarını etkisiz hale getirir.
Profesyonel ekiplerde, güvenlik bir "feature" değil, temel gereksinim olarak ele alınır. OWASP Top 10'a karşı koruma sağlayan header'lar, CI/CD pipeline'da otomatik olarak test edilir. Ayrıca test edilebilirlik açısından, middleware'in güvenlik kuralları birim testlerle doğrulanmalıdır.
// next.config.ts - Güvenlik header'ları
import type { NextConfig } from 'next';
const nextConfig: NextConfig = {
async headers() {
return [
{
source: '/(.*)',
headers: [
{ key: 'X-Frame-Options', value: 'DENY' },
{ key: 'X-Content-Type-Options', value: 'nosniff' },
{ key: 'Referrer-Policy', value: 'strict-origin-when-cross-origin' },
],
},
];
},
};
export default nextConfig;
6. Performans Optimizasyonu ve Önbellekleme Teknikleri Nasıl Uygulanır
Performans, modern web'de rekabet avantajıdır. Next.js 15, geliştiriciye önbellekleme üzerinde ayrıntılı kontrol sunar. fetch çağrılarında next.revalidate, route segment config'lerinde revalidate, ve cache: 'force-cache' gibi seçenekler ile çok katmanlı bir önbellek stratejisi kurulabilir. Bu, özellikle yüksek trafikli e-ticaret sitelerinde sunucu yükünü azaltır ve kullanıcı deneyimini iyileştirir.
Önbellekleme katmanları şunları içerir: Request Memoization (aynı istek tekrarlanmaz), Data Cache (fetch sonuçları önbelleklenir), Full Route Cache (render edilmiş React Server Component payload'ı önbelleklenir) ve Router Cache (istemci tarafında gezinme önbelleği). Her katmanın farklı invalidasyon stratejileri vardır. revalidatePath() ve revalidateTag() fonksiyonları, sunucu action'lar veya API route'lar içinden önbelleği temizlemek için kullanılır.
Bundle optimizasyonu ise kod bölme (code-splitting) ile sağlanır. Next.js otomatik olarak route bazlı kod bölme uygular. next/dynamic ile istemci bileşenleri de lazy load edilebilir. Profesyonel ekiplerde, Webpack Bundle Analyzer ile analiz yapılır ve gereksiz bağımlılıklar temizlenir. Bu, özellikle cross-platform projelerde tutarlı performans optimizasyonu sağlar.
// Route segment config - ISR ve önbellek kontrolü
export const revalidate = 3600; // 1 saat
export default async function ProductsPage() {
const products = await fetch('https://api.example.com/products', {
next: { tags: ['products'] }, // Tag bazlı invalidasyon
});
return <ProductGrid products={products} />;
}
6.1. ISR, Cache-Control ve CDN Stratejileri Nasıl Yapılandırılır
Incremental Static Regeneration (ISR), statik sayfaların belirli aralıklarla arka planda yeniden oluşturulmasıdır. revalidate parametresi ile bu süre kontrol edilir. Cache-Control header'ları ise CDN ve tarayıcı önbelleği davranışını yönetir. s-maxage (CDN) ve max-age (tarayıcı) değerleri, içeriğin ne kadar süreyle önbellekte kalacağını belirler.
CDN stratejisi, özellle global dağıtımda kritiktir. Vercel Edge Network, otomatik olarak ISR sayfalarını global CDN düğümlerine dağıtır. Ancak self-hosted senaryolarda Cloudflare veya AWS CloudFront yapılandırması gerekir. Stale-while-revalidate politikası, eski içeriğin sunulması ve arka planda güncellenmesi prensibine dayanır; bu, SaaS uygulamalarında kesintisiz hizmet için önemlidir.
Profesyonel ekiplerde, önbellek stratejisi projenin başında belirlenir. Hangi sayfaların ne kadar süreyle önbellekleneceği, hangi senaryolarda anlık güncelleme gerektiği dokümante edilir. Bu, teknik borç oluşmasını önler ve ekip üyelerinin tutarlı davranmasını sağlar.
// API Route - Cache-Control header'ları
import { NextResponse } from 'next/server';
export async function GET() {
const data = await fetchData();
return NextResponse.json(data, {
headers: {
'Cache-Control': 'public, s-maxage=60, stale-while-revalidate=300',
},
});
}
6.2. Kod Bölme (Code-Splitting) ve Bundle Optimizasyonu Örnekleri
Kod bölme, uygulamanın sadece ihtiyaç duyulan kısmının yüklenmesini sağlar. Next.js, otomatik olarak route bazlı kod bölme uygular; her sayfa ayrı bir chunk olarak yüklenir. next/dynamic ile istemci bileşenleri de lazy load edilebilir. Bu, başlangıç JavaScript boyutunu düşürür ve Time to Interactive (TTI) metriğini iyileştirir.
Bundle optimizasyonu için analiz araçları kullanılır. @next/bundle-analyzer paketi, webpack çıktısını görselleştirir ve hangi bağımlılıkların en çok yer kapladığını gösterir. Profesyonel ekiplerde, bu analiz düzenli olarak yapılır ve gereksiz kütüphaneler çıkarılır. Örneğin lodash yerine lodash-es veya native alternatifler tercih edilir.
Tree shaking, kullanılmayan kodun otomatik olarak çıkarılmasıdır. Next.js ve modern bundler'lar bu özelliği varsayılan olarak sunar. Ancak bazı kütüphaneler (özellikle CommonJS modülleri) tree shaking'e uygun değildir; bu durumda named import'lar tercih edilmelidir. Bu detaylar, performans optimizasyonunun ince ayarlarındandır.
// Dinamik import ile kod bölme
import dynamic from 'next/dynamic';
const HeavyChart = dynamic(() => import('@/components/HeavyChart'), {
ssr: false,
loading: () => <div>Grafik yükleniyor...</div>,
});
export default function AnalyticsPage() {
return <HeavyChart data={analyticsData} />;
}
6.3. Lighthouse ve Performans Profili Nasıl Ölçülür ve İyileştirilir
Lighthouse, Google'ın sunduğu otomatik performans denetim aracıdır. Core Web Vitals (LCP, FID/INP, CLS) metriklerini ölçer ve iyileştirme önerileri sunar. Next.js 15 projelerinde, next build sonrası .next/analyze/ dizininde istatistikler oluşturulabilir. Ayrıca Vercel Analytics, gerçek kullanıcı verileri (RUM - Real User Monitoring) ile Core Web Vitals'ı izler.
Performans profili çıkarmak için Chrome DevTools'un Performance sekmesi kullanılır. Burada JavaScript yürütme süresi, layout shift'ler ve uzun görevler (long tasks) görselleştirilir. Profesyonel ekiplerde, bu profil düzenli olarak çıkarılır ve regresyonları önlemek için CI/CD pipeline'a entegre edilir. Örneğin bir PR, Lighthouse skorunu %5'ten fazla düşürürse otomatik olarak reddedilebilir.
İyileştirme stratejileri arasında, görsel optimizasyon, font yükleme stratejileri (next/font ile), third-party script yönetimi ve kritik CSS çıkarımı öne çıkar. next/script bileşeni, Google Analytics gibi script'lerin lazy yüklenmesini sağlar. Bu tümleşik yaklaşım, kullanıcı deneyimini sürekli yukarı taşır.
// next/font ile optimize font yükleme
import { Inter } from 'next/font/google';
const inter = Inter({ subsets: ['latin'] });
export default function RootLayout({ children }) {
return (
<html className={inter.className}>
<body>{children}</body>
</html>
);
}
7. Uyumluluk ve Entegrasyon: Veritabanı, GraphQL, WebSocket Nasıl Bağlanır
Next.js'in sunucu tarafı yetenekleri, veritabanı ve harici servis entegrasyonlarını doğal hale getirir. Server Components ve Server Actions içinde doğrudan veritabanı sorgusu yapılabilir. Bu, ayrı bir backend API katmanı kurma ihtiyacını ortadan kaldırır. Özellikle agile süreçlerde hızlı geliştirme için bu mimari tercih edilir.
GraphQL entegrasyonu, Apollo Client veya Relay gibi kütüphaneler ile sağlanır. Ancak Server Components ile fetch kullanarak doğrudan GraphQL sorguları da yapılabilir. Bu, istemci tarafında büyük bir GraphQL client kütüphanesi yüklemek zorunda kalmadan, sunucu tarafında veri çekmeyi mümkün kılar. WebSocket ve real-time entegrasyonları ise, Next.js'in API Routes'u ile Socket.io veya native WebSocket kullanılarak gerçekleştirilir.
Profesyonel ekiplerde, entegrasyon stratejisi projenin ölçeğine göre belirlenir. Küçük projelerde Server Actions ve doğrudan DB bağlantısı yeterliyken, büyük SaaS uygulamalarında ayrı bir backend servis ve API Gateway mimarisi tercih edilebilir. Esneklik, Next.js'in en büyük avantajlarından biridir.
// Server Component içinde doğrudan DB sorgusu
import { db } from '@/lib/db';
export default async function Dashboard() {
const users = await db.user.findMany({ take: 10 });
return <UserTable users={users} />;
}
7.1. Prisma/TypeORM Entegrasyonu Nasıl Kurulur ve Örnekleri
Prisma, Next.js projelerinde en yaygın kullanılan ORM'dir. TypeScript-first yapısı, tip güvenli sorgular ve otomatik migration yönetimi sunar. Kurulum, npm install prisma @prisma/client ile başlar ve prisma/schema.prisma dosyasında model tanımları yapılır. prisma generate komutu, client kodunu üretir.
Server Components ve Server Actions içinde Prisma client kullanımı dikkat gerektirir. Her istekte yeni bir Prisma client oluşturmak yerine, singleton pattern ile tek bir instance yönetilmelidir. Aksi halde veritabanı bağlantı havuzu tükenir. TypeORM ise daha olgun bir alternatiftir ve decorator bazlı entity tanımları sunar; ancak Prisma'nın geliştirici deneyimi genellikle tercih sebebidir.
Profesyonel ekiplerde, veritabanı katmanı lib/db.ts gibi bir dosyada merkezileştirilir. Bu, test edilebilirlik ve bakımı kolaylaştırır. Ayrıca transaction yönetimi ve connection pooling, üretim ortamında mutlaka yapılandırılmalıdır. Özellikle e-ticaret ve finans uygulamalarında veri tutarlılığı kritik öneme sahiptir.
// lib/db.ts - Singleton Prisma client
import { PrismaClient } from '@prisma/client';
const globalForPrisma = global as unknown as { prisma: PrismaClient };
export const prisma = globalForPrisma.prisma || new PrismaClient();
if (process.env.NODE_ENV !== 'production') globalForPrisma.prisma = prisma;
7.2. GraphQL Modülü Nedir, Nasıl Kullanılır ve Örnekleri
GraphQL, esnek veri çekme ve tip güvenliği sunan bir sorgu dilidir. Next.js'te GraphQL kullanımı iki şekilde olabilir: istemci tarafında Apollo Client ile veya sunucu tarafında doğrudan fetch ile. Server Components ile, GraphQL endpoint'ine doğrudan HTTP isteği yapmak daha hafif bir yaklaşımdır.
Apollo Client kullanımı, client component'lerde state yönetimi ve cache için uygundur. ApolloProvider ile uygulama sarılır ve useQuery hook'u ile sorgular yapılır. Ancak Server Components ile bu hook'lar kullanılamaz; bunun yerine fetch ve async/await tercih edilir. Bu ayrım, API tasarımında bilinçli kararlar gerektirir.
Profesyonel ekiplerde, GraphQL schema tasarımı frontend ihtiyaçlarına göre şekillenir. BFF (Backend for Frontend) pattern'i ile, Next.js sunucusu kendi GraphQL gateway'i olarak görev alabilir. Bu, mikroservis arka uçlarına tek bir GraphQL yüzeyi sunar ve cross-platform istemciler (web, mobil uygulama) için tutarlı bir API sağlar.
// Server Component içinde GraphQL sorgusu
export default async function ProductsPage() {
const response = await fetch('https://api.example.com/graphql', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
query: `
query GetProducts {
products {
id
name
price
}
}
`,
}),
});
const { data } = await response.json();
return <ProductList products={data.products} />;
}
7.3. WebSocket ve Realtime Entegrasyonu Nasıl Yapılır
WebSocket, tam çift yönlü iletişim kanalı sunar ve real-time uygulamalar için idealdir. Next.js'te WebSocket entegrasyonu, API Routes ile native ws kütüphanesi veya Socket.io ile gerçekleştirilir. Ancak serverless ortamlarda (Vercel) WebSocket desteği sınırlıdır; bu nedenle real-time özellikler genellikle ayrı bir servis (örneğin Pusher, Ably) veya self-hosted Node.js sunucusu ile sağlanır.
Socket.io, WebSocket üzerine kurulu ve fallback mekanizmaları sunan popüler bir kütüphanedir. Next.js API Route'unda Socket.io server kurulabilir ancak bu, Vercel gibi tam serverless platformlarda çalışmayabilir. Bu durumda, Socket.io sunucusu ayrı bir container veya EC2 instance'da çalıştırılır ve Next.js uygulaması istemci olarak bağlanır.
Profesyonel ekiplerde, real-time mimarisi projenin ölçeğine göre seçilir. Küçük projelerde Server-Sent Events (SSE) yeterli olabilirken, büyük SaaS uygulamalarında Redis pub/sub ile desteklenen Socket.io cluster'ları tercih edilir. Kullanıcı deneyimi açısından, real-time güncellemelerin akıcı ve güvenilir olması beklenir.
// app/api/socket/route.ts - Socket.io entegrasyonu
import { Server } from 'socket.io';
export async function GET(req: Request) {
if ((global as any).io) {
return new Response('Socket.io already running');
}
const io = new Server((global as any).server);
io.on('connection', (socket) => {
socket.on('message', (msg) => {
io.emit('message', msg);
});
});
(global as any).io = io;
return new Response('Socket.io initialized');
}
7.3.1. gRPC veya Üçüncü Taraf API'lerle Güvenli Entegrasyon Teknikleri
gRPC, yüksek performanslı RPC framework'üdür ve genellikle mikroservis iletişiminde kullanılır. Next.js'te gRPC istemcisi doğrudan kullanılamaz çünkü HTTP/2 ve binary proto gerektirir. Bu durumda, bir API Gateway veya BFF katmanı aracılığıyla REST/GraphQL yüzeyi sunulur.
Üçüncü taraf API entegrasyonlarında güvenlik kritiktir. API anahtarları ve token'lar asla istemci tarafında açıkça bulunmamalıdır. Next.js Server Actions veya API Routes, bu hassas bilgileri sunucu tarafında tutar ve harici API'lere proxy görevi görür. fetch çağrılarında timeout, retry ve circuit breaker pattern'leri uygulanmalıdır.
Profesyonel ekiplerde, harici entegrasyonlar için adapter pattern kullanılır. Her üçüncü taraf servisi için ayrı bir adapter modülü yazılır ve uygulama kodu bu adapter'lar üzerinden konuşur. Bu, servis değişikliklerinde uygulama kodunun etkilenmesini önler ve test edilebilirlik sağlar. Ayrıca request/response log'lama ve hata izleme (Sentry, LogRocket) entegrasyonları standart hale getirilmelidir.
// lib/adapters/payment.ts - Üçüncü taraf API adapter'ı
export class PaymentAdapter {
async processPayment(amount: number, token: string) {
const response = await fetch(`${process.env.PAYMENT_API_URL}/charge`, {
method: 'POST',
headers: {
'Authorization': `Bearer ${process.env.PAYMENT_API_KEY}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({ amount, token }),
});
if (!response.ok) throw new Error('Payment failed');
return response.json();
}
}
8. Uygulama Senaryoları: E-Ticaret, SaaS ve Kurumsal Projelerde Nasıl Kullanılır
Next.js, farklı ölçek ve sektördeki projelerde esnekliğiyle öne çıkar. E-ticaret sitelerinde ISR ile ürün sayfaları statik olarak önbelleklenirken, sepet ve ödeme işlemleri SSR ile dinamik tutulur. SaaS uygulamalarında, App Router'ın nested layout'ları dashboard deneyimini zenginleştirir. Kurumsal projelerde ise güvenlik, ölçeklenebilirlik ve bakım kolaylığı ön plandadır.
Her senaryoda performans optimizasyonu farklı şekillerde ele alınır. E-ticaret'te sayfa hızı doğrudan dönüşüm oranını etkiler; bu nedenle görsel optimizasyon ve önbellek stratejileri agresif şekilde uygulanır. SaaS'ta ise Time to Interactive (TTI) ve smooth transitions kritiktir. Kurumsal projelerde, güvenlik header'ları, audit log'ları ve compliance gereksinimleri önceliklidir.
Profesyonel ekiplerde, projenin başında mimari kararlar dokümante edilir. Hangi sayfaların statik, hangilerinin dinamik olacağı, ödeme akışının nasıl güvenli hale getirileceği, çok kiracılı yapının nasıl tasarlanacağı gibi konular erken tartışılır. Bu, ileride teknik borç oluşmasını önler ve ekip üyelerinin hızla adapte olmasını sağlar.
// E-ticaret ürün sayfası - ISR + dinamik sepet
export const revalidate = 3600;
export default async function ProductPage({ params }) {
const product = await fetch(`https://api.example.com/products/${params.id}`);
const data = await product.json();
return (
<div>
<ProductDetails product={data} />
<AddToCartButton productId={params.id} /> {/* Client Component */}
</div>
);
}
8.1. E-Ticaret Backend ve Ödeme Entegrasyonları Örnekleri
E-ticaret projelerinde Next.js, hem frontend hem de backend görevlerini üstlenebilir. Ürün listeleme ve detay sayfaları ISR ile önbelleklenir; bu, SEO ve hız açısından kritiktir. Ödeme entegrasyonlarında ise Stripe, PayTR veya Iyzico gibi sağlayıcıların SDK'ları kullanılır. Ödeme formu ve tokenizasyon işlemleri, PCI DSS compliance'ı sağlamak için sunucu tarafında (Server Actions veya API Routes) gerçekleştirilir.
Sepet yönetimi, istemci tarafında localStorage veya Redis ile yönetilebilir. Ancak kullanıcı oturumuna bağlı sepetler için sunucu tarafı state (veritabanı veya Redis) tercih edilir. Checkout akışı, multi-step form olarak tasarlanır ve her adımda Server Actions ile validasyon yapılır. Bu, hem güvenli hem de hızlı bir deneyim sunar.
Profesyonel ekiplerde, ödeme entegrasyonu test ortamında kapsamlı şekilde test edilir. Webhook handler'ları, idempotency kontrolleri ve hata durumlarında rollback mekanizmaları uygulanır. Ayrıca kullanıcı deneyimi açısından, ödeme sürecindeki her adımda açık geri bildirim (loading state, hata mesajları) sunulur.
// app/actions/payment.ts - Stripe entegrasyonu
'use server';
import Stripe from 'stripe';
const stripe = new Stripe(process.env.STRIPE_SECRET_KEY!);
export async function createPaymentIntent(amount: number) {
const paymentIntent = await stripe.paymentIntents.create({
amount: amount * 100, // kuruş cinsinden
currency: 'try',
automatic_payment_methods: { enabled: true },
});
return { clientSecret: paymentIntent.client_secret };
}
8.2. Çok Kiracılı (Multi-Tenant) SaaS Mimarisi Nasıl Tasarlanır
Multi-tenant SaaS, tek bir kod tabanıyla birden fazla müşteriye (tenant) hizmet sunmayı ifade eder. Next.js'te bu, subdomain veya path bazlı izolasyon ile sağlanır. Örneğin tenant1.app.com veya app.com/tenant1 gibi yapılar kullanılabilir. Middleware'de gelen isteğin hangi tenant'a ait olduğu tespit edilir ve veritabanı bağlantısı buna göre yönlendirilir.
Veritabanı stratejisi üç şekilde olabilir: tek veritabanı + tenant ID ile satır bazlı izolasyon, schema bazlı izolasyon (PostgreSQL), veya veritabanı bazlı izolasyon. Next.js Server Components ile, her istekte tenant context'i otomatik olarak ayarlanabilir. Prisma'ın multi-tenant desteği veya Drizzle ORM ile bu yönetim kolaylaşır.
Profesyonel ekiplerde, tenant izolasyonu güvenlik açısından en üst düzeydedir. Bir tenant'ın verisi asla başka bir tenant'a sızmamalıdır. Bu, middleware'de strict kontroller ve veritabanı seviyesinde Row Level Security (RLS) politikaları ile sağlanır. Ayrıca her tenant için custom branding, domain ve özelleştirme imkanları sunulur.
// middleware.ts - Tenant çözümleme
import { NextResponse } from 'next/server';
export function middleware(request: Request) {
const host = request.headers.get('host');
const tenant = host?.split('.')[0]; // tenant1.app.com
const requestHeaders = new Headers(request.headers);
requestHeaders.set('x-tenant-id', tenant || 'default');
return NextResponse.next({
request: { headers: requestHeaders },
});
}
8.3. Oturum Yönetimi, Kimlik Doğrulama ve Güvenlik Senaryoları
Kimlik doğrulama, modern web uygulamalarının temel taşıdır. Next.js'te Auth.js (NextAuth.js v5), Clerk, Lucia veya custom JWT çözümleri kullanılabilir. Auth.js, App Router ile tam entegre çalışır ve OAuth sağlayıcıları (Google, GitHub), credentials login ve magic link desteği sunar. Session yönetimi, JWT veya veritabanı tabanlı (session token) olarak yapılandırılabilir.
Oturum yönetimi, özellikle SaaS uygulamalarında karmaşık hale gelebilir. Refresh token rotasyonu, çoklu cihaz oturum yönetimi ve oturum sonlandırma (kill switch) gibi özellikler gerekebilir. Next.js Server Components içinde auth() fonksiyonu ile oturum bilgisine erişim, client component'lerde ise useSession() hook'u kullanılır.
Güvenlik senaryoları arasında, CSRF koruması, XSS önleme, rate limiting ve güvenlik header'ları öne çıkar. Next.js'in built-in CSRF koruması, form gönderimlerini güvenli hale getirir. Content Security Policy (CSP) header'ları, inline script ve harici kaynakların kontrolü ile XSS riskini azaltır. Profesyonel ekiplerde, bu konular CI/CD pipeline'da otomatik güvenlik taramaları ile desteklenir.
// auth.ts - Auth.js yapılandırması
import NextAuth from 'next-auth';
import Google from 'next-auth/providers/google';
export const { handlers, signIn, signOut, auth } = NextAuth({
providers: [Google],
callbacks: {
async session({ session, token }) {
session.user.id = token.sub;
return session;
},
},
});
9. Geliştirme Araçları ve İş Akışları: CLI, Testing, CI/CD Nasıl Entegre Edilir
Next.js ekosistemi, geliştirici verimliliğini artıran zengin bir araç seti sunar. create-next-app ile proje iskeleti saniyeler içinde kurulur. Turbopack, geliştirme sunucusunu 10 kata kadar hızlandırır ve büyük projelerde bile anlık hot reload sağlar. TypeScript, ESLint, Tailwind CSS ve daha fazlası tek komutla entegre edilir.
Testing stratejisi, birim testler (Jest/Vitest), entegrasyon testleri (React Testing Library) ve E2E testleri (Playwright) katmanlarından oluşur. Next.js 15, React Server Components'in test edilmesi için özel utility'ler sunar. next/test-utils paketi, server component render'ı ve async test senaryolarını destekler. Bu, test edilebilirlik standartlarını yükseltir.
CI/CD entegrasyonu, Vercel ile neredeyse otomatik hale gelir. GitHub repo'suna bağlanan proje, her push'ta preview deployment, ana dala merge'de production deployment alır. Self-hosted senaryolarda GitHub Actions, GitLab CI veya Jenkins pipeline'ları ile Docker build ve deploy adımları otomatize edilir. Agile süreçlerde bu hız, iterasyon döngüsünü kısaltır.
# Next.js CLI komutları
npx create-next-app@latest my-app --typescript --tailwind --app
npm run dev # Geliştirme sunucusu (Turbopack)
npm run build # Üretim build'i
npm run start # Üretim sunucusu
npm run lint # ESLint kontrolü
9.1. Next CLI ile Proje İskeleti ve Komut Örnekleri
Next.js CLI, proje yönetiminin merkezidir. create-next-app şablonu, TypeScript, Tailwind, ESLint ve App Router ile tam yapılandırılmış bir proje oluşturur. --example flag'i ile resmi örnekler (with-redux, with-docker, with-storybook) hızla klonlanabilir. Bu, yeni projelerde standart yapıyı korur ve ekip üyelerinin hızla başlamasını sağlar.
Geliştirme komutları arasında next dev (Turbopack ile hızlı geliştirme), next build (optimizasyonlu üretim build'i) ve next start (üretim sunucusu) öne çıkar. next lint ESLint kurallarını kontrol eder, next type-check TypeScript derlemesi yapar. Bu komutlar, pre-commit hook'ları ve CI pipeline'larında otomatik olarak çalıştırılır.
Profesyonel ekiplerde, proje iskeleti şirket standartlarına göre özelleştirilir. Ortak bir template repo (template repository) oluşturulur ve yeni projeler bu template'den türetilir. Bu template, ortak UI kitaplığı, auth yapılandırması, logging standartları ve CI/CD pipeline'larını içerir. Böylece her yeni proje, bilinen ve test edilmiş bir temel üzerine kurulur.
# Standart proje oluşturma
npx create-next-app@latest . \
--typescript \
--tailwind \
--eslint \
--app \
--src-dir \
--import-alias "@/*"
# Örnek proje klonlama
npx create-next-app@latest --example with-docker
9.2. Unit ve Integration Test Yazımı, Jest ve Playwright Örnekleri
Unit testler, bileşenlerin ve utility fonksiyonların izole olarak test edilmesini sağlar. Next.js'te Jest veya Vitest tercih edilebilir. React Testing Library, bileşenleri kullanıcı perspektifinden test eder; implementation detaylarına bağımlı kalmaz. Server Components testi için @testing-library/react ve next/test-utils birlikte kullanılır.
Integration testler, birden fazla bileşenin veya modülün birlikte çalışmasını doğrular. Örneğin bir form gönderiminin, Server Action'ı tetikleyip veritabanını güncellemesi ve sayfayı revalidate etmesi bir entegrasyon test senaryosudur. MSW (Mock Service Worker) ile API çağrıları mock'lanır ve gerçek ağ isteği yapılmadan test edilir.
E2E testlerde Playwright, tarayıcıda gerçek kullanıcı akışlarını simüle eder. Next.js uygulamasının build edilmiş hali üzerinde çalışır ve CI/CD pipeline'ında çalıştırılır. Profesyonel ekiplerde, kritik kullanıcı yolculukları (login, ödeme, kayıt) için E2E testler zorunlu tutulur. Bu, regresyonları önler ve kullanıcı deneyimi kalitesini garanti altına alır.
// tests/page.test.tsx - Server Component testi
import { render, screen } from '@testing-library/react';
import HomePage from '@/app/page';
jest.mock('@/lib/db', () => ({
prisma: {
product: {
findMany: jest.fn().mockResolvedValue([
{ id: '1', name: 'Ürün A', price: 100 },
]),
},
},
}));
describe('HomePage', () => {
it('ürünleri render eder', async () => {
const page = await HomePage();
render(page);
expect(screen.getByText('Ürün A')).toBeInTheDocument();
});
});
9.3. Vercel, CI/CD Boru Hattı ve Otomatik Dağıtım Pratikleri
Vercel, Next.js'in doğal ev sahibidir. GitHub, GitLab veya Bitbucket repo'suna bağlanan proje, her push'ta otomatik olarak build edilir ve preview URL'i oluşturur. Ana dala merge edildiğinde ise production deployment tetiklenir. Bu zero-config yaklaşım, agile ekiplerde hızlı iterasyon yapmayı mümkün kılar.
CI/CD boru hattı, sadece deploy'dan ibaret değildir. Her PR'da lint, type-check, unit test ve E2E test çalıştırılır. Lighthouse CI ile performans skorları ölçülür ve regresyon varsa PR otomatik olarak reddedilir. Bu, "bozuk kod üretime çıkmasın" prensibini otomatize eder. Self-hosted senaryolarda Docker multi-stage build ile optimize edilmiş imajlar oluşturulur ve Kubernetes cluster'a deploy edilir.
Profesyonel ekiplerde, deployment stratejisi belirlenirken rollback kolaylığı göz önünde bulundurulur. Blue-green deployment veya canary release pattern'leri, yeni versiyonun riskini azaltır. Ayrıca feature flag sistemleri (LaunchDarkly, Unleash) ile kod deploy edilir ancak özellik kullanıcılara aşamalı olarak açılır. Bu, SaaS uygulamalarında güvenli sürüm yönetimi için standarttır.
# .github/workflows/ci.yml - GitHub Actions pipeline'ı
name: CI/CD Pipeline
on:
push:
branches: [main, develop]
pull_request:
branches: [main]
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: '20'
- run: npm ci
- run: npm run lint
- run: npm run type-check
- run: npm run test:ci
- run: npm run build
10. UI/UX Entegrasyonu ve Frontend İş Akışı: API Tasarımı ile Kullanıcı Deneyimi Nasıl İyileştirilir (UI/UX; Responsive Tasarım)
API tasarımı ile kullanıcı deneyimi arasındaki ilişki sıklıkla göz ardı edilir. Ancak iyi tasarlanmış bir API, frontend'in daha hızlı, daha tutarlı ve daha az hata ile çalışmasını sağlar. Next.js'te Server Components, API verisini sunucuda çekip HTML olarak iletir; bu, istemcideki loading state karmaşasını ortadan kaldırır. Kullanıcı sayfaya geldiğinde içerik hazır bekler.
Responsive tasarım sadece CSS medya sorguları ile sınırlı değildir. API yanıtları da cihaz tipine göre şekillendirilebilir. Örneğin mobil cihazlar için daha az alan döndüren bir endpoint, bant genişliğini korur ve kullanıcı deneyimini iyileştirir. Next.js middleware'de User-Agent analizi yapılarak, mobil kullanıcılara farklı veri seti sunulabilir.
Profesyonel ekiplerde, API kontratları (OpenAPI/Swagger) frontend ve backend ekipleri arasında ortak dil oluşturur. TypeScript ile tip güvenliği sağlanır ve zod veya valibot gibi kütüphanelerle runtime validasyon yapılır. Bu, runtime hatalarını azaltır ve kullanıcıya karşılıklı tutarlı bir arayüz sunar. Ayrıca error boundary'ler ve fallback UI'lar ile API hataları zarif şekilde yönetilir.
// lib/api.ts - Tip güvenli API client
import { z } from 'zod';
const ProductSchema = z.object({
id: z.string(),
name: z.string(),
price: z.number().positive(),
});
export type Product = z.infer<typeof ProductSchema>;
export async function getProducts(): Promise<Product[]> {
const res = await fetch('/api/products');
const data = await res.json();
return z.array(ProductSchema).parse(data); // Runtime validasyon
}
10.1. REST vs GraphQL Seçim Kriterleri ve Frontend Etkileri
REST ve GraphQL arasındaki seçim, projenin ihtiyaçlarına göre değişir. REST, basitlik ve önbelleklenebilirlik avantajı sunar. Next.js'te REST endpoint'ler, HTTP caching (Cache-Control, ETag) ile doğal olarak uyumludur. Ancak over-fetching ve under-fetching sorunları, özellikle mobil cihazlarda bant genişliği israfına yol açabilir.
GraphQL ise istemcinin tam olarak ihtiyaç duyduğu veriyi çekmesini sağlar. Next.js Server Components ile GraphQL sorguları sunucuda çalıştırılır ve istemciye sadece HTML gönderilir. Bu, GraphQL client kütüphanesi yükünü ortadan kaldırır. Ancak GraphQL caching daha karmaşıktır; persisted queries ve Apollo Server cache gibi çözümler gerekebilir.
Profesyonel ekiplerde, seçim şu kriterlere göre yapılır: veri modelinin karmaşıklığı, istemci çeşitliliği (web, mobil uygulama, desktop), önbellek gereksinimleri ve ekip uzmanlığı. Özellikle cross-platform projelerde, GraphQL tek bir endpoint ile tüm istemcilere hizmet sunar. Ancak basit CRUD uygulamalarında REST, daha az karmaşıklık ve daha iyi caching ile yeterli olabilir.
// REST endpoint - Cache-friendly
export async function GET() {
const products = await prisma.product.findMany();
return NextResponse.json(products, {
headers: {
'Cache-Control': 'public, s-maxage=300',
},
});
}
// GraphQL sorgusu - Server Component içinde
const query = `
query { products { id name price } }
`;
10.2. API Versiyonlama, Geriye Dönük Uyumluluk ve Sürüm Stratejileri
API versiyonlama, değişen gereksinimlere rağmen mevcut istemcilerin çalışmaya devam etmesini sağlar. Next.js'te versiyonlama, URL path'i (/api/v1/, /api/v2/) veya header bazlı (Accept: application/vnd.api.v2+json) yapılabilir. URL bazlı versiyonlama daha açık ve debug edilebilirdir.
Geriye dönük uyumluluk (backward compatibility), mevcut endpoint'lerin davranışını bozmadan yeni özellikler eklemeyi ifade eder. Yeni alanlar opsiyonel olarak eklenir, mevcut alanlar değiştirilmez. Deprecation header'ları (Sunset) ile eski versiyonların kullanımdan kaldırılacağı tarih bildirilir. Bu, özellikle SaaS uygulamalarında üçüncü taraf entegrasyonları olan müşteriler için kritiktir.
Profesyonel ekiplerde, API değişiklikleri bir changelog ve migration guide ile dokümante edilir. Semver (Semantic Versioning) prensipleri takip edilir: major versiyonlar breaking change, minor versiyonlar yeni özellik, patch versiyonlar bug fix içerir. Ayrıca API gateway katmanı (Kong, AWS API Gateway) ile versiyon yönlendirme ve rate limiting merkezi olarak yönetilir.
// app/api/v2/products/route.ts - Versiyonlu API
import { NextResponse } from 'next/server';
export async function GET() {
const products = await prisma.product.findMany({
include: { category: true }, // v2'de yeni ilişki
});
return NextResponse.json({
version: '2.0',
data: products,
meta: { total: products.length },
});
}
10.2.1. Mobil Ön Yüz İçin Bant Genişliği ve Kritik CSS Optimizasyonu Teknikleri
Mobil cihazlar, sınırlı bant genişliği ve işlem gücüne sahiptir. Bu nedenle mobil ön yüz optimizasyonu, kullanıcı deneyimini doğrudan etkiler. Next.js next/font ile font'lar otomatik olarak optimize edilir ve self-host edilir; bu, harici font CDN'lerine bağımlılığı ortadan kaldırır. Ayrıca font-display: swap ile metin anında render edilir, font yüklenene kadar sistem font'u kullanılır.
Kritik CSS, sayfanın ilk görünür alanını (above the fold) render etmek için gerekli olan stil kurallarıdır. Next.js, otomatik olarak kritik CSS çıkarımı yapar ve <head> içinde inline olarak enjekte eder. Bu, render blocking CSS dosyalarının indirilmesini beklemeden sayfanın hızla gösterilmesini sağlar. next/head ve metadata API ile kritik meta tag'leri ve preload direktifleri yönetilir.
Profesyonel ekiplerde, mobil ön yüz için ayrı bir optimizasyon stratejisi belirlenir. Görsel boyutları mobil breakpoint'ler için ayrı olarak hesaplanır, lazy loading agresif şekilde uygulanır ve third-party script'ler (analytics, chat widget) async veya defer ile yüklenir. Lighthouse mobil skoru, her PR'da kontrol edilir ve 90+ hedeflenir.
// app/layout.tsx - Kritik font ve meta optimizasyonu
import { Inter } from 'next/font/google';
const inter = Inter({
subsets: ['latin'],
display: 'swap',
variable: '--font-inter',
});
export const metadata = {
viewport: 'width=device-width, initial-scale=1',
themeColor: '#000000',
};
export default function RootLayout({ children }) {
return (
<html className={inter.variable}>
<body className="font-sans antialiased">{children}</body>
</html>
);
}
11. Sonuç: Üretime Geçiş, Bakım ve Maliyet Optimizasyonu Nasıl Planlanır (Web Geliştirme; E-Ticaret; SaaS)
Next.js projesinin üretime geçişi, sadece npm run build ve deploy etmekten ibaret değildir. Kapsamlı bir planlama, beklenmeyen sorunları önler ve sürdürülebilir bir operasyon sağlar. Web geliştirme sürecinde, üretim öncesi bir checklist hazırlanmalı ve bu checklist her deployment öncesi takip edilmelidir. Performans, güvenlik, erişilebilirlik ve SEO kriterleri bu listede yer alır.
E-ticaret ve SaaS projelerinde maliyet optimizasyonu, altyapı seçiminden başlar. Vercel'in serverless modeli, düşük trafikli projelerde maliyet etkindir ancak yüksek trafikte self-hosted çözümler daha ekonomik olabilir. CDN kullanımı, sunucu yükünü azaltır ve bant genişliği maliyetlerini düşürür. Ayrıca ISR ve önbellek stratejileri, veritabanı sorgu maliyetlerini minimize eder.
Bakım ve sürüm yönetimi, projenin uzun ömürlü olmasını sağlar. Teknik borç düzenli olarak değerlendirilir ve refactor sprint'lerine dahil edilir. Dependency güncellemeleri otomatize edilir (Dependabot, Renovate) ve güvenlik açıkları için CVE taramaları düzenli yapılır. Profesyonel ekiplerde, bu süreçler dokümante edilir ve yeni ekip üyelerinin hızla adapte olması sağlanır.
// next.config.ts - Üretim optimizasyonları
import type { NextConfig } from 'next';
const nextConfig: NextConfig = {
output: 'standalone', // Optimize edilmiş Docker imajı
poweredByHeader: false,
compress: true,
images: {
remotePatterns: [
{ protocol: 'https', hostname: 'cdn.example.com' },
],
},
};
export default nextConfig;
11.1. Yayın Öncesi Checklist ve Performans Kabul Kriterleri
Yayın öncesi checklist, üretime geçişin kalite standartlarını garanti altına alır. Bu liste şunları içermelidir: Lighthouse skorları (LCP < 2.5s, CLS < 0.1, INP < 200ms), Core Web Vitals geçiş skorları, güvenlik taraması sonuçları (OWASP ZAP, Snyk), erişilebilirlik audit'i (axe-core), ve SEO kontrolleri (meta tag'ler, structured data, sitemap).
Performans kabul kriterleri, objektif ve ölçülebilir olmalıdır. Örneğin "ana sayfa 3 saniyenin altında yüklenmelidir" gibi bir kriter, Lighthouse ve WebPageTest ile doğrulanabilir. Bundle boyutu limitleri (örneğin ilk JS chunk < 200KB) ve API yanıt süreleri (p95 < 500ms) de bu kriterlere dahil edilir. Bu kriterler, CI/CD pipeline'ında otomatik olarak kontrol edilir.
Profesyonel ekiplerde, bu checklist her major release öncesi takip edilir ve imzalanır. Ayrıca staging ortamında load test'ler (k6, Artillery) yapılır ve uygulamanın beklenen trafik altında nasıl davrandığı gözlemlenir. Bu, e-ticaret sitelerinde Black Friday gibi yoğun dönemlerde yaşanabilecek sorunları önceden tespit eder.
# Lighthouse CI yapılandırması
npx lhci autorun --config=lighthouserc.js
# lighthouserc.js
module.exports = {
ci: {
assert: {
preset: 'lighthouse:recommended',
assertions: {
'categories:performance': ['warn', { minScore: 0.9 }],
'categories:accessibility': ['error', { minScore: 0.95 }],
},
},
},
};
11.2. Bakım, Sürüm Yönetimi ve Teknik Borç Azaltma Stratejileri
Bakım, yazılımın yaşam döngüsünün en uzun fazıdır. Next.js projelerinde, düzenli dependency güncellemeleri kritik öneme sahiptir. npm outdated komutu ile eski paketler tespit edilir ve npm audit ile güvenlik açıkları kontrol edilir. Major versiyon güncellemeleri (örneğin Next.js 14'ten 15'e), ayrı bir branch'te test edilir ve regresyon testleri tamamlandıktan sonra merge edilir.
Sürüm yönetimi, Git flow veya trunk-based development prensiplerine göre yapılır. Semantic versioning (semver) takip edilir ve her release bir changelog ile dokümante edilir. Feature flag'ler, yeni özelliklerin kontrollü şekilde açılmasını sağlar; bu, SaaS uygulamalarında A/B test ve gradual rollout için standarttır.
Teknik borç azaltma, refactor sprint'lerine ve "boy scout rule" (her zaman kodu bulduğundan daha iyi bırak) prensibine dayanır. Kod kalitesi metrikleri (cyclomatic complexity, test coverage) düzenli ölçülür ve düşüş trendi gösteren alanlar önceliklendirilir. Profesyonel ekiplerde, teknik borç bir Jira/epic olarak takip edilir ve her çeyrekte allocate edilen zamanla azaltılır. Bu yaklaşım, uzun vadede geliştirme hızını korur ve web geliştirme sürecinin sürdürülebilirliğini garanti altına alır.
# Dependency güncelleme ve güvenlik kontrolü
npm outdated
npm audit fix
npm update next react react-dom
# Test coverage raporu
npm run test -- --coverage --watchAll=false
Next.js, modern web geliştirmenin gereksinimlerini karşılayan kapsamlı bir framework'tür. Sunucu tarafı render etme, statik site oluşturma, API rotaları ve edge computing yetenekleri ile e-ticaretten SaaS'a, kurumsal projelerden mobil uygulama arka uçlarına kadar geniş bir yelpazede kullanılabilir. Performans optimizasyonu, kullanıcı deneyimi ve geliştirici verimliliği arasındaki dengeyi başarıyla kurar.
Profesyonel ekiplerde Next.js tercih edilmesinin temel sebebi, ekosistem bütünlüğü ve üretime hazır çözümler sunmasıdır. TypeScript, Tailwind, testing araçları ve CI/CD entegrasyonları tek bir komutla yapılandırılabilir. Bu, agile süreçlerde hızlı iterasyon yapmayı ve teknik borç riskini azaltmayı mümkün kılar. Ayrıca Vercel platformu ile global dağıtım, otomatik ölçeklenme ve analitik araçlar, operasyonel yükü minimize eder.
Sonuç olarak, Next.js sadece bir React framework'ü değil; modern web uygulamaları için stratejik bir temeldir. Doğru mimari kararlar, önbellek stratejileri ve güvenlik pratikleri ile, ölçeklenebilir ve sürdürülebilir uygulamalar inşa etmek mümkündür. Geliştiricilerin bu rehberdeki prensipleri projelerine uygulamaları, hem teknik kaliteyi hem de son kullanıcı memnuniyetini artıracaktır.
Noves Team
Noves Digital: 2020'den beri İzmir merkezli, 3 kişilik tutkulu yazılım ekibi. Web & mobil uygulama, özel yazılım çözümleri. React, Node.js, Python uzmanlığı. Agile çalışma, şeffaf iletişim, %100 zamanında teslimat. Sizin teknoloji partneriniz.