Türkçe

Gelen istekleri yakalamak ve değiştirmek için güçlü bir özellik olan Next.js middleware'i keşfedin. Pratik örneklerle kimlik doğrulama, yetkilendirme, yönlendirme ve A/B testlerini nasıl uygulayacağınızı öğrenin.

Next.js Middleware: Dinamik Uygulamalar için İstek Yakalamada Uzmanlaşma

Next.js middleware, gelen istekleri rotalarınıza ulaşmadan önce yakalamak ve değiştirmek için esnek ve güçlü bir yol sunar. Bu yetenek, kimlik doğrulama ve yetkilendirmeden yönlendirme ve A/B testine kadar geniş bir yelpazede özellikleri uygulamanıza olanak tanırken aynı zamanda performansı optimize eder. Bu kapsamlı kılavuz, Next.js middleware'in temel kavramlarını anlatacak ve onu nasıl etkili bir şekilde kullanacağınızı gösterecektir.

Next.js Middleware Nedir?

Next.js'teki middleware, bir istek tamamlanmadan önce çalışan bir fonksiyondur. Size şunları yapma olanağı sağlar:

Middleware fonksiyonları, projenizin kök dizinindeki middleware.ts (veya middleware.js) dosyasında tanımlanır. Uygulamanızdaki her rota için veya yapılandırılabilir eşleştiricilere (matchers) dayalı olarak belirli rotalar için yürütülürler.

Temel Kavramlar ve Avantajlar

Request (İstek) Nesnesi

request nesnesi, gelen istekle ilgili bilgilere erişim sağlar, bunlar arasında:

Response (Yanıt) Nesnesi

Middleware fonksiyonları, isteğin sonucunu kontrol etmek için bir Response nesnesi döndürür. Aşağıdaki yanıtları kullanabilirsiniz:

Eşleştiriciler (Matchers)

Eşleştiriciler, middleware'inizin hangi rotalara uygulanması gerektiğini belirtmenize olanak tanır. Düzenli ifadeler veya yol desenleri kullanarak eşleştiriciler tanımlayabilirsiniz. Bu, middleware'inizin yalnızca gerektiğinde çalışmasını sağlayarak performansı artırır ve ek yükü azaltır.

Edge Runtime

Next.js middleware, kullanıcılarınıza yakın bir konumda dağıtılabilen hafif bir JavaScript çalışma zamanı ortamı olan Edge Runtime üzerinde çalışır. Bu yakınlık, gecikmeyi en aza indirir ve uygulamanızın genel performansını, özellikle küresel olarak dağıtılmış kullanıcılar için iyileştirir. Edge Runtime, Vercel'in Edge Network'ünde ve diğer uyumlu platformlarda mevcuttur. Edge Runtime'ın bazı sınırlamaları vardır, özellikle de Node.js API'lerinin kullanımı.

Pratik Örnekler: Middleware Özelliklerini Uygulama

1. Kimlik Doğrulama (Authentication)

Kimlik doğrulama middleware'i, kullanıcıların giriş yapmasını gerektiren rotaları korumak için kullanılabilir. İşte çerezleri kullanarak kimlik doğrulamanın nasıl uygulanacağına dair bir örnek:


// middleware.ts
import { NextResponse } from 'next/server'
import type { NextRequest } from 'next/server'

export function middleware(request: NextRequest) {
 const token = request.cookies.get('auth_token');

 if (!token) {
 return NextResponse.redirect(new URL('/login', request.url))
 }

 return NextResponse.next()
}

export const config = {
 matcher: ['/dashboard/:path*'],
}

Bu middleware, bir auth_token çerezinin varlığını kontrol eder. Çerez bulunmazsa, kullanıcı /login sayfasına yönlendirilir. config.matcher, bu middleware'in yalnızca /dashboard altındaki rotalar için çalışması gerektiğini belirtir.

Küresel Perspektif: Farklı bölgelerden gelen kullanıcılara hizmet vermek için kimlik doğrulama mantığını çeşitli kimlik doğrulama yöntemlerini (ör. OAuth, JWT) destekleyecek ve farklı kimlik sağlayıcılarla (ör. Google, Facebook, Azure AD) entegre olacak şekilde uyarlayın.

2. Yetkilendirme (Authorization)

Yetkilendirme middleware'i, kullanıcı rollerine veya izinlerine göre kaynaklara erişimi kontrol etmek için kullanılabilir. Örneğin, yalnızca belirli kullanıcıların erişebileceği bir yönetici panonuz olabilir.


// middleware.ts
import { NextResponse } from 'next/server'
import type { NextRequest } from 'next/server'

export async function middleware(request: NextRequest) {
 const token = request.cookies.get('auth_token');

 if (!token) {
 return NextResponse.redirect(new URL('/login', request.url))
 }

 // Örnek: Bir API'den kullanıcı rollerini al (kendi asıl mantığınızla değiştirin)
 const userResponse = await fetch('https://api.example.com/userinfo', {
 headers: {
 Authorization: `Bearer ${token}`,
 },
 });
 const userData = await userResponse.json();

 if (userData.role !== 'admin') {
 return NextResponse.redirect(new URL('/unauthorized', request.url))
 }

 return NextResponse.next()
}

export const config = {
 matcher: ['/admin/:path*'],
}

Bu middleware, kullanıcının rolünü alır ve admin rolüne sahip olup olmadıklarını kontrol eder. Değilse, /unauthorized sayfasına yönlendirilirler. Bu örnek, bir yer tutucu API uç noktası kullanır. `https://api.example.com/userinfo` adresini kendi gerçek kimlik doğrulama sunucusu uç noktanızla değiştirin.

Küresel Perspektif: Kullanıcı verilerini işlerken veri gizliliği düzenlemelerine (ör. GDPR, CCPA) dikkat edin. Hassas bilgileri korumak ve yerel yasalara uyumu sağlamak için uygun güvenlik önlemlerini uygulayın.

3. Yönlendirme (Redirection)

Yönlendirme middleware'i, kullanıcıları konumlarına, dillerine veya diğer kriterlere göre yönlendirmek için kullanılabilir. Örneğin, kullanıcıları IP adreslerine göre web sitenizin yerelleştirilmiş bir sürümüne yönlendirebilirsiniz.


// middleware.ts
import { NextResponse } from 'next/server'
import type { NextRequest } from 'next/server'

export function middleware(request: NextRequest) {
 const country = request.geo?.country || 'US'; // Coğrafi konum başarısız olursa varsayılan olarak ABD

 if (country === 'DE') {
 return NextResponse.redirect(new URL('/de', request.url))
 }

 if (country === 'FR') {
 return NextResponse.redirect(new URL('/fr', request.url))
 }

 return NextResponse.next()
}

export const config = {
 matcher: ['/'],
}

Bu middleware, kullanıcının ülkesini IP adresine göre kontrol eder ve onları web sitesinin uygun yerelleştirilmiş sürümüne (Almanya için /de, Fransa için /fr) yönlendirir. Coğrafi konum başarısız olursa, varsayılan olarak ABD sürümüne yönlendirilir. Bunun, geo özelliğinin mevcut olmasına (örneğin, Vercel'de dağıtıldığında) dayandığını unutmayın.

Küresel Perspektif: Web sitenizin birden fazla dili ve para birimini desteklediğinden emin olun. Kullanıcılara tercih ettikleri dili veya bölgeyi manuel olarak seçme seçeneği sunun. Her yerel ayar için uygun tarih ve saat biçimlerini kullanın.

4. A/B Testi

Middleware, kullanıcıları bir sayfanın farklı varyantlarına rastgele atayarak ve davranışlarını izleyerek A/B testi uygulamak için kullanılabilir. İşte basitleştirilmiş bir örnek:


// middleware.ts
import { NextResponse } from 'next/server'
import type { NextRequest } from 'next/server'

function getRandomVariant() {
 return Math.random() < 0.5 ? 'A' : 'B';
}

export function middleware(request: NextRequest) {
 let variant = request.cookies.get('variant')?.value;

 if (!variant) {
 variant = getRandomVariant();
 const response = NextResponse.next();
 response.cookies.set('variant', variant);
 return response;
 }

 if (variant === 'B') {
 return NextResponse.rewrite(new URL('/variant-b', request.url));
 }

 return NextResponse.next();
}

export const config = {
 matcher: ['/'],
}

Bu middleware, kullanıcıları 'A' veya 'B' varyantına atar. Bir kullanıcının zaten bir variant çerezi yoksa, rastgele bir tane atanır ve ayarlanır. 'B' varyantına atanan kullanıcılar /variant-b sayfasına yeniden yazılır. Daha sonra hangi varyantın daha etkili olduğunu belirlemek için her varyantın performansını izlersiniz.

Küresel Perspektif: A/B testleri tasarlarken kültürel farklılıkları göz önünde bulundurun. Bir bölgede iyi çalışan bir şey, başka bir bölgedeki kullanıcılarla aynı etkiyi yaratmayabilir. A/B test platformunuzun farklı bölgelerdeki gizlilik düzenlemeleriyle uyumlu olduğundan emin olun.

5. Özellik Bayrakları (Feature Flags)

Özellik bayrakları, yeni kod dağıtmadan uygulamanızdaki özellikleri etkinleştirmenize veya devre dışı bırakmanıza olanak tanır. Middleware, bir kullanıcının kullanıcı kimliğine, konumuna veya diğer kriterlere göre belirli bir özelliğe erişip erişemeyeceğini belirlemek için kullanılabilir.


// middleware.ts
import { NextResponse } from 'next/server'
import type { NextRequest } from 'next/server'

export async function middleware(request: NextRequest) {
 // Örnek: Bir API'den özellik bayraklarını al
 const featureFlagsResponse = await fetch('https://api.example.com/featureflags', {
 headers: {
 'X-User-Id': 'user123',
 },
 });
 const featureFlags = await featureFlagsResponse.json();

 if (featureFlags.new_feature_enabled) {
 // Yeni özelliği etkinleştir
 return NextResponse.next();
 } else {
 // Yeni özelliği devre dışı bırak (ör. alternatif bir sayfaya yönlendir)
 return NextResponse.redirect(new URL('/alternative-page', request.url));
 }
}

export const config = {
 matcher: ['/new-feature'],
}

Bu middleware, bir API'den özellik bayraklarını alır ve new_feature_enabled bayrağının ayarlanıp ayarlanmadığını kontrol eder. Eğer ayarlanmışsa, kullanıcı /new-feature sayfasına erişebilir. Aksi takdirde, /alternative-page sayfasına yönlendirilirler.

Küresel Perspektif: Yeni özellikleri farklı bölgelerdeki kullanıcılara aşamalı olarak sunmak için özellik bayraklarını kullanın. Bu, özelliği daha geniş bir kitleye yayınlamadan önce performansı izlemenize ve sorunları gidermenize olanak tanır. Ayrıca, özellik bayrağı sisteminizin küresel olarak ölçeklendiğinden ve kullanıcının konumundan bağımsız olarak tutarlı sonuçlar verdiğinden emin olun. Özellik sunumları için bölgesel düzenleyici kısıtlamaları göz önünde bulundurun.

İleri Düzey Teknikler

Middleware Zincirleme

Bir istek üzerinde bir dizi işlem gerçekleştirmek için birden fazla middleware fonksiyonunu birbirine zincirleyebilirsiniz. Bu, karmaşık mantığı daha küçük, daha yönetilebilir modüllere ayırmak için yararlı olabilir.


// middleware.ts
import { NextResponse } from 'next/server'
import type { NextRequest } from 'next/server'

export function middleware(request: NextRequest) {
 const response = NextResponse.next();

 // Birinci middleware fonksiyonu
 const token = request.cookies.get('auth_token');
 if (!token) {
 return NextResponse.redirect(new URL('/login', request.url))
 }

 // İkinci middleware fonksiyonu
 response.headers.set('x-middleware-custom', 'value');

 return response;
}

export const config = {
 matcher: ['/dashboard/:path*'],
}

Bu örnek, bir arada iki middleware gösterir. Birincisi kimlik doğrulama yapar ve ikincisi özel bir başlık ayarlar.

Ortam Değişkenlerini Kullanma

API anahtarları ve veritabanı kimlik bilgileri gibi hassas bilgileri middleware fonksiyonlarınızda sabit kodlamak yerine ortam değişkenlerinde saklayın. Bu, güvenliği artırır ve uygulamanızın yapılandırmasını yönetmeyi kolaylaştırır.


// middleware.ts
import { NextResponse } from 'next/server'
import type { NextRequest } from 'next/server'

const API_KEY = process.env.API_KEY;

export async function middleware(request: NextRequest) {
 const response = await fetch('https://api.example.com/data', {
 headers: {
 'X-API-Key': API_KEY,
 },
 });

 // ...
}

export const config = {
 matcher: ['/data'],
}

Bu örnekte, API_KEY bir ortam değişkeninden alınır.

Hata Yönetimi

Beklenmedik hataların uygulamanızı çökertmesini önlemek için middleware fonksiyonlarınızda sağlam hata yönetimi uygulayın. İstisnaları yakalamak ve hataları uygun şekilde günlüğe kaydetmek için try...catch bloklarını kullanın.


// middleware.ts
import { NextResponse } from 'next/server'
import type { NextRequest } from 'next/server'

export async function middleware(request: NextRequest) {
 try {
 const response = await fetch('https://api.example.com/data');
 // ...
 } catch (error) {
 console.error('Veri alınırken hata oluştu:', error);
 return NextResponse.error(); // Veya bir hata sayfasına yönlendir
 }
}

export const config = {
 matcher: ['/data'],
}

En İyi Uygulamalar

Yaygın Sorunları Giderme

Sonuç

Next.js middleware, dinamik ve kişiselleştirilmiş web uygulamaları oluşturmak için güçlü bir araçtır. İstek yakalamada uzmanlaşarak, kimlik doğrulama ve yetkilendirmeden yönlendirme ve A/B testine kadar geniş bir yelpazede özellikler uygulayabilirsiniz. Bu kılavuzda belirtilen en iyi uygulamaları takip ederek, küresel kullanıcı tabanınızın ihtiyaçlarını karşılayan yüksek performanslı, güvenli ve ölçeklenebilir uygulamalar oluşturmak için Next.js middleware'den yararlanabilirsiniz. Next.js projelerinizde yeni olasılıkların kilidini açmak ve olağanüstü kullanıcı deneyimleri sunmak için middleware'in gücünü benimseyin.