// Exemplu rapid: Server Action simplu pentru update profil
// Beneficiu: zero API route boilerplate
export async function updateProfile(prevState: any, formData: FormData) {
const name = formData.get('name');
if (!name || name.length < 3) {
return { error: 'Numele e prea scurt' };
}
try {
await db.user.update({ data: { name } });
revalidatePath('/profile');
return { success: true };
} catch (e) {
return { error: 'Ceva n-a mers la baza de date' };
}
}Salutare. Văd des discuția asta pe Slack și pe forumuri: „Mai are rost să scriu API routes în Next.js 14/15?”. Răspunsul scurt e: depinde cât de mult vrei să te lupți cu framework-ul sau cu limitările de infrastructură. Am trecut prin faza aia în care scriam fetch('/api/data', { method: 'POST' ... }) pentru orice formular amărât, iar Server Actions chiar au schimbat jocul, dar nu sunt soluția universală la care visam.
Formularele: Unde Server Actions strălucesc
La un proiect recent cu vreo 12 formulare complexe de checkout și setări de profil, am trecut totul pe Server Actions. Am economisit cam 30% din codul de frontend pur și simplu pentru că am scăpat de managementul manual de loading, error și data states.
Când folosești useActionState (fostul useFormState), tot fluxul devine mult mai fluid. Nu mai ai nevoie de un endpoint separat pe care să-l păzești cu validări duplicate. Scrii funcția, o marchezi cu 'use server', o pasezi în action={formAction} și Next.js se ocupă de restul. Marele câștig aici e că ai type-safety end-to-end fără să te chinui cu biblioteci externe de sincronizare. Plus că funcționează (teoretic) și fără JavaScript pe client, deși în 2024 rareori mai e asta o prioritate reală.
File Upload: Capcana în care mulți picăm
Aici m-am ars cel mai tare. Am încercat să fac un sistem de upload de documente (PDF-uri de 10-20MB) folosind exclusiv Server Actions. În local, totul mergea brici. În producție, pe Vercel, am dat de limita de 4.5MB pentru payload-ul de request la funcțiile serverless.
Server Actions sunt, la bază, niște POST-uri către aceeași pagină, iar corpul cererii trebuie să fie serializat. Dacă ai fișiere mari, serverul va consuma multă memorie încercând să proceseze acel FormData înainte să apuci tu să faci ceva cu el. Pentru upload-uri serioase, recomand în continuare un API Route clasic unde poți folosi busboy sau, și mai bine, generezi un presigned URL și trimiți fișierul direct în S3/R2 din browser. Scapi de timeout-uri și de costuri inutile de execuție pe serverul tău.
Webhooks și integrare cu terți
Dacă încerci să primești un webhook de la Stripe sau Shopify printr-un Server Action, pierzi timpul degeaba. Server Actions sunt gândite strict pentru interacțiunea user-browser. Ele au nevoie de headere specifice de Next.js ca să știe ce „acțiune” să invoce. Un serviciu extern n-o să știe niciodată să trimită header-ul Next-Action corect.
Pentru orice înseamnă apel extern — fie că e un webhook, un cron job extern sau un endpoint pe care vrei să-l expui pentru o aplicație mobilă — API Routes (route.ts) rămân singura soluție validă. Ai control total pe metode (GET, POST, PUT, DELETE), pe headerele de cache și pe autentificarea custom.
Trade-off-ul sincer
Server Actions sunt superbe pentru UX și viteză de dezvoltare când „proprietarul” datelor e chiar userul tău care dă click. API Routes sunt pentru infrastructură și interoperabilitate.
Am avut un caz unde am încercat să forțez Server Actions pentru un dashboard public (fără auth). A fost o greșeală tactică pentru că am pierdut posibilitatea de a face caching la nivel de HTTP pe acele cereri. Server Actions sunt mereu POST, deci adio cache la nivel de Edge sau browser.
Voi ce abordare aveți? Mai folosiți API routes pentru formulare simple sau ați trecut complet pe acțiuni?