// app/actions.ts
'use server'
import { revalidatePath } from 'next/cache'
export async function updateProfile(prevState: any, formData: FormData) {
const name = formData.get('name') as string
const bio = formData.get('bio') as string
if (!name || name.length < 3) {
return { error: 'Numele trebuie să aibă cel puțin 3 caractere.' }
}
try {
// Simulare salvare în baza de date
// await db.user.update({ data: { name, bio } })
revalidatePath('/profile')
return { success: true, error: null }
} catch (err) {
return { error: 'Eroare la salvarea datelor în DB.' }
}
}Salutare! Văd tot mai des pe grupuri oameni care aruncă cu Server Actions în absolut orice problemă, de parcă API route-urile clasice ar fi deprecated. Spoiler: nu sunt. Am migrat recent un proiect de SaaS cu vreo 12.000 de utilizatori activi de pe API-uri clasice pe Server Actions (unde a avut sens) și am redus bundle-ul pe client cu vreo 15%, dar am dat și cu capul de pragul de sus.
Hai să le luăm la bani mărunți, pe cazuri reale de utilizare, ca să nu faceți aceleași greșeli de începător.
1. Formularele simple: Server Actions e rege
Dacă ai de făcut un formular clasic de contact, editare profil sau adăugare de comentarii, Server Actions sunt geniale. Scapi de fetch('/api/ceva'), scapi de gestionat manual stări de loading și error cu useState peste tot.
Am avut un formular de feedback unde foloseam React Hook Form și un API Route. L-am rescris complet cu un Server Action și useActionState (fostul useFormState). Codul s-a redus la jumătate. Marele plus? Funcționează și dacă userul are o conexiune atât de slabă încât JS-ul nu s-a încărcat încă în pagină (progressive enhancement). În plus, Next.js se ocupă automat de protecția CSRF pentru aceste acțiuni, scutindu-te de boilerplate de securitate.
2. File Upload: Atenție la memoria serverului
Aici am făcut prima greșeală pe proiectul de care vă spuneam. Am zis să fac upload de imagini de profil (până în 5MB) direct printr-un Server Action, trimițând un FormData clasic.
Local, pe mașina mea de dezvoltare, totul mergea brici. În schimb, în producție (pe serverless, pe Vercel), ne-am trezit cu timeout-uri și consum uriaș de memorie când s-au nimerit vreo 20 de useri să uploadeze imagini simultan. De ce? Server Actions serializează datele și, de cele mai multe ori, fișierul este citit complet în memorie înainte să apuci tu să îl trimiți în S3 sau Cloudinary.
Regula mea de aur acum:
- Fișiere mici (sub 1MB, gen un avatar mic sau un CSV scurt)? Server Actions e perfect.
- Fișiere mari sau multiple? API Route clasic care generează un presigned URL de S3, iar clientul face upload direct în storage-ul extern. Economisești bandwidth și memorie pe serverul tău.
3. Webhook-uri externe: API Routes sunt obligatorii
Aici nu există termen de comparație. Webhook-urile de la Stripe, Shopify sau orice alt serviciu terț au nevoie de un endpoint HTTP clasic (un URL public de tip POST) și au nevoie de acces la request-ul brut (raw body) pentru validarea semnăturii criptografice.
Server Actions sunt create special pentru a fi apelate din interiorul aplicației tale Next.js, fiind strâns legate de build-ul tău. Nu le poți expune ca URL-uri publice standard pe care să le apeleze Stripe când se confirmă o plată. Pentru asta, folosești în continuare ruta clasică app/api/webhook/route.ts.
Trade-off-ul pe care nu-ți dorești să-l ignori
Server Actions rulează în contextul de server al Next.js, ceea ce înseamnă că împart aceleași limite de timeout ca și paginile randate pe server (de exemplu, 15 secunde pe planul hobby de Vercel). Dacă ai o acțiune care procesează imagini grele sau face interogări complexe în bază de date, o să îți crape cu timeout mult mai repede decât un API route configurat separat.
Voi ce strategie folosiți în ultima vreme? Ați trecut complet pe Server Actions sau păstrați API-urile clasice pentru orice înseamnă mutare de date mai complexă?