Next.js 14 Sunucu Eylemleri için kapsamlı bir rehber. Form işleme en iyi uygulamaları, veri doğrulama, güvenlik konuları ve modern web uygulamaları oluşturmak için ileri teknikleri kapsar.
Next.js 14 Sunucu Eylemleri: Form İşleme En İyi Uygulamalarında Uzmanlaşma
Next.js 14, performanslı ve kullanıcı dostu web uygulamaları oluşturmak için güçlü özellikler sunar. Bunlar arasında, Sunucu Eylemleri (Server Actions), form gönderimlerini ve veri mutasyonlarını doğrudan sunucuda işlemenin dönüştürücü bir yolu olarak öne çıkıyor. Bu rehber, form işleme, veri doğrulama, güvenlik ve ileri teknikler için en iyi uygulamalara odaklanarak Next.js 14'teki Sunucu Eylemlerine kapsamlı bir genel bakış sunmaktadır. Sağlam ve ölçeklenebilir web uygulamaları oluşturmanıza yardımcı olacak pratik örnekleri keşfedecek ve uygulanabilir bilgiler sunacağız.
Next.js Sunucu Eylemleri Nedir?
Sunucu Eylemleri, sunucuda çalışan ve doğrudan React bileşenlerinden çağrılabilen eşzamansız fonksiyonlardır. Form gönderimlerini ve veri mutasyonlarını işlemek için geleneksel API rotalarına olan ihtiyacı ortadan kaldırarak basitleştirilmiş kod, geliştirilmiş güvenlik ve artırılmış performans sağlarlar. Sunucu Eylemleri, React Sunucu Bileşenleridir (RSC), yani sunucuda yürütülürler, bu da daha hızlı ilk sayfa yüklemelerine ve geliştirilmiş SEO'ya yol açar.
Sunucu Eylemlerinin Temel Faydaları:
- Basitleştirilmiş Kod: Ayrı API rotalarına olan ihtiyacı ortadan kaldırarak standart kod miktarını azaltın.
- Geliştirilmiş Güvenlik: Sunucu taraflı yürütme, istemci taraflı güvenlik açıklarını en aza indirir.
- Artırılmış Performans: Daha hızlı yanıt süreleri için veri mutasyonlarını doğrudan sunucuda yürütün.
- Optimize Edilmiş SEO: Daha iyi arama motoru indekslemesi için sunucu taraflı render'dan yararlanın.
- Tür Güvenliği: TypeScript ile uçtan uca tür güvenliğinden yararlanın.
Next.js 14 Projenizi Kurma
Sunucu Eylemlerine dalmadan önce, bir Next.js 14 projesinin kurulu olduğundan emin olun. Sıfırdan başlıyorsanız, aşağıdaki komutu kullanarak yeni bir proje oluşturun:
npx create-next-app@latest my-next-app
Sunucu Bileşenleri ve Eylemlerinden tam olarak yararlanmak için projenizin app
dizin yapısını kullandığından emin olun.
Sunucu Eylemleri ile Temel Form İşleme
Basit bir örnekle başlayalım: bir veritabanında yeni bir öğe oluşturmak için veri gönderen bir form. Bir giriş alanı ve bir gönder düğmesi olan basit bir form kullanacağız.
Örnek: Yeni Bir Öğe Oluşturma
İlk olarak, React bileşeniniz içinde bir Sunucu Eylemi fonksiyonu tanımlayın. Bu fonksiyon, form gönderme mantığını sunucuda işleyecektir.
// app/components/CreateItemForm.tsx
'use client';
import { useState } from 'react';
async function createItem(formData: FormData) {
'use server'
const name = formData.get('name') as string;
// Veritabanı etkileşimini simüle et
console.log('Öğe oluşturuluyor:', name);
await new Promise((resolve) => setTimeout(resolve, 1000)); // Gecikmeyi simüle et
console.log('Öğe başarıyla oluşturuldu!');
}
export default function CreateItemForm() {
const [isSubmitting, setIsSubmitting] = useState(false);
async function handleSubmit(formData: FormData) {
setIsSubmitting(true);
await createItem(formData);
setIsSubmitting(false);
}
return (
);
}
Açıklama:
'use client'
yönergesi, bunun bir istemci bileşeni olduğunu belirtir.createItem
fonksiyonu, bir Sunucu Eylemi olduğunu belirten'use server'
yönergesi ile işaretlenmiştir.handleSubmit
fonksiyonu, sunucu eylemini çağıran istemci tarafı bir fonksiyondur. Ayrıca gönderme sırasında düğmenin devre dışı bırakılması gibi UI durumunu da yönetir.<form>
elemanınınaction
prop'u,handleSubmit
fonksiyonuna ayarlanmıştır.formData.get('name')
metodu, 'name' giriş alanının değerini alır.await new Promise
, bir veritabanı işlemini simüle eder ve gecikme ekler.
Veri Doğrulama
Veri doğrulama, veri bütünlüğünü sağlamak ve güvenlik açıklarını önlemek için çok önemlidir. Sunucu Eylemleri, sunucu taraflı doğrulama yapmak için mükemmel bir fırsat sunar. Bu yaklaşım, yalnızca istemci taraflı doğrulama ile ilişkili riskleri azaltmaya yardımcı olur.
Örnek: Girdi Verilerini Doğrulama
Doğrulama mantığını dahil etmek için createItem
Sunucu Eylemini değiştirin.
// app/components/CreateItemForm.tsx
'use client';
import { useState } from 'react';
async function createItem(formData: FormData) {
'use server'
const name = formData.get('name') as string;
if (!name || name.length < 3) {
throw new Error('Öğe adı en az 3 karakter uzunluğunda olmalıdır.');
}
// Veritabanı etkileşimini simüle et
console.log('Öğe oluşturuluyor:', name);
await new Promise((resolve) => setTimeout(resolve, 1000)); // Gecikmeyi simüle et
console.log('Öğe başarıyla oluşturuldu!');
}
export default function CreateItemForm() {
const [isSubmitting, setIsSubmitting] = useState(false);
const [errorMessage, setErrorMessage] = useState(null);
async function handleSubmit(formData: FormData) {
setIsSubmitting(true);
setErrorMessage(null);
try {
await createItem(formData);
} catch (error: any) {
setErrorMessage(error.message || 'Bir hata oluştu.');
} finally {
setIsSubmitting(false);
}
}
return (
{errorMessage && {errorMessage}
}
);
}
Açıklama:
createItem
fonksiyonu artıkname
alanının geçerli olup olmadığını kontrol ediyor (en az 3 karakter uzunluğunda).- Doğrulama başarısız olursa, bir hata fırlatılır.
handleSubmit
fonksiyonu, Sunucu Eylemi tarafından fırlatılan hataları yakalamak ve kullanıcıya bir hata mesajı göstermek için güncellenmiştir.
Doğrulama Kütüphaneleri Kullanımı
Daha karmaşık doğrulama senaryoları için, aşağıdaki gibi doğrulama kütüphanelerini kullanmayı düşünün:
- Zod: TypeScript öncelikli bir şema bildirim ve doğrulama kütüphanesi.
- Yup: Değerleri ayrıştırmak, doğrulamak ve dönüştürmek için bir JavaScript şema oluşturucu.
İşte Zod kullanarak bir örnek:
// app/utils/validation.ts
import { z } from 'zod';
export const CreateItemSchema = z.object({
name: z.string().min(3, 'Öğe adı en az 3 karakter uzunluğunda olmalıdır.'),
});
// app/components/CreateItemForm.tsx
'use client';
import { useState } from 'react';
import { CreateItemSchema } from '../utils/validation';
async function createItem(formData: FormData) {
'use server'
const name = formData.get('name') as string;
const validatedFields = CreateItemSchema.safeParse({ name });
if (!validatedFields.success) {
return { errors: validatedFields.error.flatten().fieldErrors };
}
// Veritabanı etkileşimini simüle et
console.log('Öğe oluşturuluyor:', name);
await new Promise((resolve) => setTimeout(resolve, 1000)); // Gecikmeyi simüle et
console.log('Öğe başarıyla oluşturuldu!');
}
export default function CreateItemForm() {
const [isSubmitting, setIsSubmitting] = useState(false);
const [errorMessage, setErrorMessage] = useState(null);
async function handleSubmit(formData: FormData) {
setIsSubmitting(true);
setErrorMessage(null);
try {
await createItem(formData);
} catch (error: any) {
setErrorMessage(error.message || 'Bir hata oluştu.');
} finally {
setIsSubmitting(false);
}
}
return (
{errorMessage && {errorMessage}
}
);
}
Açıklama:
CreateItemSchema
, Zod kullanarakname
alanı için doğrulama kurallarını tanımlar.safeParse
metodu, girdi verilerini doğrulamaya çalışır. Doğrulama başarısız olursa, hataları içeren bir nesne döndürür.errors
nesnesi, doğrulama hataları hakkında ayrıntılı bilgi içerir.
Güvenlik Hususları
Sunucu Eylemleri, kodu sunucuda çalıştırarak güvenliği artırır, ancak uygulamanızı yaygın tehditlere karşı korumak için güvenlik en iyi uygulamalarını takip etmek hala çok önemlidir.
Siteler Arası İstek Sahteciliğini (CSRF) Önleme
CSRF saldırıları, bir web sitesinin kullanıcının tarayıcısına duyduğu güvenden yararlanır. CSRF saldırılarını önlemek için CSRF koruma mekanizmalarını uygulayın.
Next.js, Sunucu Eylemlerini kullanırken CSRF korumasını otomatik olarak yönetir. Framework, her form gönderimi için bir CSRF token'ı oluşturur ve doğrular, böylece isteğin uygulamanızdan kaynaklandığından emin olur.
Kullanıcı Kimlik Doğrulama ve Yetkilendirme İşlemleri
Yalnızca yetkili kullanıcıların belirli eylemleri gerçekleştirebildiğinden emin olun. Hassas verileri ve işlevselliği korumak için kimlik doğrulama ve yetkilendirme mekanizmalarını uygulayın.
İşte bir Sunucu Eylemini korumak için NextAuth.js kullanan bir örnek:
// app/components/CreateItemForm.tsx
'use client';
import { useState } from 'react';
import { getServerSession } from 'next-auth';
import { authOptions } from '../../app/api/auth/[...nextauth]/route';
async function createItem(formData: FormData) {
'use server'
const session = await getServerSession(authOptions);
if (!session) {
throw new Error('Yetkisiz');
}
const name = formData.get('name') as string;
// Veritabanı etkileşimini simüle et
console.log('Öğe oluşturuluyor:', name, 'kullanıcı tarafından:', session.user?.email);
await new Promise((resolve) => setTimeout(resolve, 1000)); // Gecikmeyi simüle et
console.log('Öğe başarıyla oluşturuldu!');
}
export default function CreateItemForm() {
const [isSubmitting, setIsSubmitting] = useState(false);
const [errorMessage, setErrorMessage] = useState(null);
async function handleSubmit(formData: FormData) {
setIsSubmitting(true);
setErrorMessage(null);
try {
await createItem(formData);
} catch (error: any) {
setErrorMessage(error.message || 'Bir hata oluştu.');
} finally {
setIsSubmitting(false);
}
}
return (
{errorMessage && {errorMessage}
}
);
}
Açıklama:
getServerSession
fonksiyonu, kullanıcının oturum bilgilerini alır.- Kullanıcının kimliği doğrulanmamışsa (oturum yoksa), bir hata fırlatılır ve Sunucu Eyleminin yürütülmesi engellenir.
Girdi Verilerini Temizleme
Siteler Arası Komut Dosyası Çalıştırma (XSS) saldırılarını önlemek için girdi verilerini temizleyin. XSS saldırıları, kötü niyetli kodun bir web sitesine enjekte edilmesiyle meydana gelir ve potansiyel olarak kullanıcı verilerini veya uygulama işlevselliğini tehlikeye atar.
Sunucu Eylemlerinizde işlemeden önce kullanıcı tarafından sağlanan girdiyi temizlemek için DOMPurify
veya sanitize-html
gibi kütüphaneleri kullanın.
İleri Teknikler
Temelleri ele aldığımıza göre, Sunucu Eylemlerini etkili bir şekilde kullanmak için bazı ileri teknikleri inceleyelim.
İyimser Güncellemeler (Optimistic Updates)
İyimser güncellemeler, eylemin başarılı olacağı varsayımıyla, sunucu onaylamadan önce bile kullanıcı arayüzünü anında güncelleyerek daha iyi bir kullanıcı deneyimi sunar. Eylem sunucuda başarısız olursa, kullanıcı arayüzü önceki durumuna geri döndürülür.
// app/components/UpdateItemForm.tsx
'use client';
import { useState } from 'react';
async function updateItem(id: string, formData: FormData) {
'use server'
const name = formData.get('name') as string;
// Veritabanı etkileşimini simüle et
console.log('Öğe güncelleniyor:', id, 'yeni ad:', name);
await new Promise((resolve) => setTimeout(resolve, 1000)); // Gecikmeyi simüle et
// Başarısızlığı simüle et (gösterim amaçlı)
const shouldFail = Math.random() < 0.5;
if (shouldFail) {
throw new Error('Öğe güncellenemedi.');
}
console.log('Öğe başarıyla güncellendi!');
return { name }; // Güncellenmiş adı döndür
}
export default function UpdateItemForm({ id, initialName }: { id: string; initialName: string }) {
const [isSubmitting, setIsSubmitting] = useState(false);
const [errorMessage, setErrorMessage] = useState(null);
const [itemName, setItemName] = useState(initialName);
async function handleSubmit(formData: FormData) {
setIsSubmitting(true);
setErrorMessage(null);
// UI'yi iyimser bir şekilde güncelle
const newName = formData.get('name') as string;
setItemName(newName);
try {
const result = await updateItem(id, formData);
// Başarılı olursa, güncelleme zaten setItemName aracılığıyla UI'ye yansıtılmıştır
} catch (error: any) {
setErrorMessage(error.message || 'Bir hata oluştu.');
// Hata durumunda UI'yi geri al
setItemName(initialName);
} finally {
setIsSubmitting(false);
}
}
return (
Mevcut Ad: {itemName}
{errorMessage && {errorMessage}
}
);
}
Açıklama:
- Sunucu Eylemini çağırmadan önce, kullanıcı arayüzü
setItemName
kullanılarak yeni öğe adıyla anında güncellenir. - Sunucu Eylemi başarısız olursa, kullanıcı arayüzü orijinal öğe adına geri döndürülür.
Verileri Yeniden Doğrulama
Bir Sunucu Eylemi veriyi değiştirdikten sonra, kullanıcı arayüzünün en son değişiklikleri yansıttığından emin olmak için önbelleğe alınmış verileri yeniden doğrulamanız gerekebilir. Next.js, verileri yeniden doğrulamak için birkaç yol sunar:
- Yolu Yeniden Doğrula (Revalidate Path): Belirli bir yol için önbelleği yeniden doğrulayın.
- Etiketi Yeniden Doğrula (Revalidate Tag): Belirli bir etiketle ilişkili veriler için önbelleği yeniden doğrulayın.
İşte yeni bir öğe oluşturduktan sonra bir yolu yeniden doğrulama örneği:
// app/components/CreateItemForm.tsx
'use client';
import { useState } from 'react';
import { revalidatePath } from 'next/cache';
async function createItem(formData: FormData) {
'use server'
const name = formData.get('name') as string;
// Veritabanı etkileşimini simüle et
console.log('Öğe oluşturuluyor:', name);
await new Promise((resolve) => setTimeout(resolve, 1000)); // Gecikmeyi simüle et
console.log('Öğe başarıyla oluşturuldu!');
revalidatePath('/items'); // /items yolunu yeniden doğrula
}
export default function CreateItemForm() {
const [isSubmitting, setIsSubmitting] = useState(false);
const [errorMessage, setErrorMessage] = useState(null);
async function handleSubmit(formData: FormData) {
setIsSubmitting(true);
setErrorMessage(null);
try {
await createItem(formData);
} catch (error: any) {
setErrorMessage(error.message || 'Bir hata oluştu.');
} finally {
setIsSubmitting(false);
}
}
return (
{errorMessage && {errorMessage}
}
);
}
Açıklama:
revalidatePath('/items')
fonksiyonu,/items
yolu için önbelleği geçersiz kılar ve bu yola bir sonraki isteğin en son verileri getirmesini sağlar.
Sunucu Eylemleri İçin En İyi Uygulamalar
Sunucu Eylemlerinin faydalarını en üst düzeye çıkarmak için aşağıdaki en iyi uygulamaları göz önünde bulundurun:
- Sunucu Eylemlerini Küçük ve Odaklı Tutun: Sunucu Eylemleri tek ve iyi tanımlanmış bir görevi yerine getirmelidir. Okunabilirliği ve test edilebilirliği korumak için Sunucu Eylemleri içinde karmaşık mantıktan kaçının.
- Açıklayıcı İsimler Kullanın: Sunucu Eylemlerinize amaçlarını açıkça belirten açıklayıcı isimler verin.
- Hataları Zarifçe Yönetin: Kullanıcıya bilgilendirici geri bildirim sağlamak ve uygulama çökmelerini önlemek için sağlam hata yönetimi uygulayın.
- Verileri Kapsamlı Bir Şekilde Doğrulayın: Veri bütünlüğünü sağlamak ve güvenlik açıklarını önlemek için kapsamlı veri doğrulaması yapın.
- Sunucu Eylemlerinizi Güvence Altına Alın: Hassas verileri ve işlevselliği korumak için kimlik doğrulama ve yetkilendirme mekanizmalarını uygulayın.
- Performansı Optimize Edin: Sunucu Eylemlerinizin performansını izleyin ve hızlı yanıt süreleri sağlamak için gerektiğinde optimize edin.
- Önbelleğe Almayı Etkili Bir Şekilde Kullanın: Performansı artırmak ve veritabanı yükünü azaltmak için Next.js'in önbelleğe alma mekanizmalarından yararlanın.
Yaygın Tuzaklar ve Bunlardan Kaçınma Yolları
Sunucu Eylemleri çok sayıda avantaj sunsa da, farkında olunması gereken bazı yaygın tuzaklar vardır:
- Aşırı Karmaşık Sunucu Eylemleri: Tek bir Sunucu Eylemi içine çok fazla mantık koymaktan kaçının. Karmaşık görevleri daha küçük, daha yönetilebilir fonksiyonlara bölün.
- Hata Yönetimini İhmal Etme: Beklenmedik hataları yakalamak ve kullanıcıya yararlı geri bildirim sağlamak için her zaman hata yönetimini dahil edin.
- Güvenlik En İyi Uygulamalarını Göz Ardı Etme: Uygulamanızı XSS ve CSRF gibi yaygın tehditlerden korumak için güvenlik en iyi uygulamalarını takip edin.
- Verileri Yeniden Doğrulamayı Unutma: Kullanıcı arayüzünü güncel tutmak için bir Sunucu Eylemi veriyi değiştirdikten sonra önbelleğe alınmış verileri yeniden doğruladığınızdan emin olun.
Sonuç
Next.js 14 Sunucu Eylemleri, form gönderimlerini ve veri mutasyonlarını doğrudan sunucuda işlemenin güçlü ve verimli bir yolunu sunar. Bu rehberde özetlenen en iyi uygulamaları takip ederek, sağlam, güvenli ve performanslı web uygulamaları oluşturabilirsiniz. Kodunuzu basitleştirmek, güvenliği artırmak ve genel kullanıcı deneyimini iyileştirmek için Sunucu Eylemlerini benimseyin. Bu ilkeleri entegre ederken, geliştirme seçimlerinizin küresel etkisini göz önünde bulundurun. Formlarınızın ve veri işleme süreçlerinizin çeşitli uluslararası kitleler için erişilebilir, güvenli ve kullanıcı dostu olduğundan emin olun. Kapsayıcılığa olan bu bağlılık, yalnızca uygulamanızın kullanılabilirliğini artırmakla kalmayacak, aynı zamanda küresel ölçekte erişimini ve etkinliğini de genişletecektir.