// Exemplu de Server Action cu validare Zod, perfect pentru formulare
'use server';
import { z } from 'zod';
import { db } from '@/lib/db';
import { revalidatePath } from 'next/cache';
const profileSchema = z.object({
username: z.string().min(3).max(20),
bio: z.string().max(160).optional(),
});
export async function updateProfile(prevState: any, formData: FormData) {
const validatedFields = profileSchema.safeParse({
username: formData.get('username'),
bio: formData.get('bio'),
});
if (!validatedFields.success) {
return { error: 'Date invalide introduse.' };
}
try {
await db.user.update({
where: { id: 'current-user-id' },
data: validatedFields.data,
});
revalidatePath('/profile');
return { success: true };
} catch (err) {
return { error: 'Eroare la salvarea în baza de date.' };
}
}Next.js ne-a cam zăpăcit în ultimul timp cu Server Actions, promovându-le ca pe soluția ideală care ne scapă de vechile rute de API. După ce am migrat un proiect mărișor de e-commerce cu vreo 12k utilizatori activi, mi-am dat seama că Server Actions nu sunt răspunsul la orice.
Ambele abordări își au locul lor în arhitectura unei aplicații moderne. Hai să le luăm la bani mărunți prin prisma a trei cazuri concrete pe care le lovești în aproape orice proiect real: formulare, upload de fișiere și webhook-uri.
1. Form Submit: Locul unde Server Actions strălucesc
Pentru formulare simple sau mutații rapide de date, Server Actions sunt geniale. Înainte, trebuia să scrii un endpoint de API (/api/user/update), să faci fetch din client, să gestionezi stările de loading și erorile manual în componentă.
Cu Server Actions, scrii o simplă funcție asincronă marcată cu 'use server' și o legi direct de proprietatea action a formularului. Primești type safety din oficiu de la baza de date până în UI, fără generatoare de cod terțe.
Trade-off sincer: Dacă ai nevoie de interfețe extrem de interactive, cum ar fi validarea în timp real la fiecare tastă apăsată (keystroke validation) sau un comportament complex de debouncing, Server Actions devin greoaie. Pentru asta, tot un API clasic apelat cu axios sau react-query îți oferă un control mai fin asupra stării din client.
2. File Upload: Zona gri unde poți să-ți blochezi serverul
Am încercat inițial să urc imagini de produs direct printr-un Server Action, trimițând un obiect FormData. Tehnic, funcționează. Practic, ne-am lovit rapid de probleme de performanță.
Server Actions serializează tot corpul cererii și îl țin în memorie ca File sau Blob pe serverul Node.js înainte ca tu să poți face ceva cu el. Dacă ai 50 de utilizatori care urcă simultan imagini de 8-10MB, memoria RAM a serverului (sau instanța serverless pe Vercel) va exploda instant.
Cum e mai bine? Pentru fișiere mari, soluția optimă este să folosești un Route Handler (route.ts) doar pentru a genera un URL presemnat (presigned URL) de la AWS S3 sau Cloudflare R2. Clientul ia acel URL și face upload-ul direct în storage-ul extern, ocolind complet serverul tău Next.js. Salvezi lățime de bandă și resurse prețioase.
3. Webhook-uri de la terți: Aici n-ai de ales
Dacă integrezi Stripe, Shopify, Paddle sau orice serviciu care trimite notificări de tip webhook (de exemplu, când se confirmă o plată), Server Actions ies complet din discuție.
Server Actions sunt, la bază, apeluri de tip RPC (Remote Procedure Call) mascate sub cereri POST cu headere specifice Next.js (cum ar fi Next-Action). Nu le poți expune ca endpoint-uri publice standard cu o structură fixă pe care un serviciu extern să o poată apela direct.
Aici Route Handlers sunt singura opțiune corectă. Ai nevoie de o rută fizică /api/webhooks/stripe unde să poți citi corpul brut al request-ului (raw body) pentru a valida semnătura Stripe și a trimite înapoi un status HTTP 200 curat.
Concluzie
Regula mea de aur după un an de testat Next.js în producție este simplă:
- Folosește Server Actions pentru acțiuni inițiate direct de utilizatorul tău în UI (adaugă în coș, șterge un comentariu, actualizează profilul).
- Rămâi pe Route Handlers (API Routes) pentru integrări cu sisteme externe, webhook-uri, rute publice de API și generare de URL-uri pentru upload direct în cloud.
Voi ce abordare folosiți pentru upload-ul de fișiere în noile versiuni de Next.js? Rămâneți pe API routes sau ați trecut pe upload direct în client cu presigned URLs?