Najvažnije iz članka
- Server Actions eliminiraju potrebu za ručnim API rutama i smanjuju količinu koda.
- Obavezna je uporaba biblioteka poput Zod za validaciju podataka na serveru.
- Sigurnost se postiže provjerom sesije unutar same akcije, a ne putem skrivenih polja na klijentu.
- Koristite revalidatePath i revalidateTag za precizno upravljanje keširanjem podataka.
- useActionState hook je ključan za rukovanje stanjima učitavanja i povratnim informacijama u UI-ju.
Sadržaj članka
Next.js nastavlja dominirati React ekosustavom, a verzija 16 donosi dodatno poliranje koncepta koji je iz korijena promijenio način na koji razmišljamo o 'full-stack' JavaScript razvoju: Server Actions. Iako su uvedene kao stabilna značajka u verziji 13.4, tek s najnovijim iteracijama dobivamo punu zrelost API-ja, bolju integraciju s Reactovim useActionState hookom i robusnije sigurnosne protokole koji su nužni za rad u produkcijskom okruženju. Ovaj tutorial provest će vas kroz sve aspekte implementacije, od osnovne sintakse do naprednih tehnika validacije i optimizacije performansi.
Server Actions nisu samo novi način slanja formi; one predstavljaju fundamentalni pomak u arhitekturi. Umjesto ručnog kreiranja API ruta (/api/data), definiranja HTTP metoda (POST, PUT, DELETE) i parsiranja JSON tijela, programeri sada mogu definirati asinkrone funkcije koje se izvršavaju direktno na poslužitelju, a pozivaju se s klijenta kao obične JavaScript funkcije. To eliminira ogroman dio 'boilerplate' koda i smanjuje površinu za bugove koji često nastaju zbog neusklađenosti tipova podataka između frontenda i backenda.
Razumijevanje arhitekture Server Actions
Prije nego što zaronimo u kod, važno je razumjeti kako Server Actions funkcioniraju pod haubom. Kada definirate funkciju s direktivom 'use server', Next.js automatski kreira HTTP endpoint za vas. Prilikom poziva te funkcije s klijentske komponente, Next.js šalje POST zahtjev koji sadrži serijalizirane argumente. Ono što je ključno jest da se odgovor vraća u formatu koji omogućuje Next.js-u da osvježi UI bez potpunog ponovnog učitavanja stranice, zadržavajući stanje klijentske aplikacije.
Ova uska integracija omogućuje značajke poput 'progressive enhancementa'. Ako korisnik ima isključen JavaScript, Server Action će i dalje raditi unutar <form> elementa jer se oslanja na standardni HTML form submission. U produkcijskom okruženju, to znači da je vaša aplikacija pristupačnija i otpornija na loše mrežne uvjete. Međutim, s velikom moći dolazi i velika odgovornost, pogotovo kada je riječ o sigurnosti i validaciji podataka koji dolaze s klijenta.
Implementacija prve Server Action funkcije
Započnimo s konkretnim primjerom. Pretpostavimo da gradimo sustav za upravljanje komentarima. Prvi korak je kreiranje datoteke u kojoj ćemo definirati naše akcije, primjerice app/lib/actions.ts. Korištenje zasebne datoteke je preporučena praksa jer omogućuje lakše dijeljenje koda i jasnu distinkciju između klijentskog i serverskog koda.
'use server';
import { revalidatePath } from 'next/cache';
import { redirect } from 'next/navigation';
import { z } from 'zod';
const CommentSchema = z.object({
text: z.string().min(3).max(500),
postId: z.string(),
});
export async function createComment(formData: FormData) {
const rawInput = {
text: formData.get('text'),
postId: formData.get('postId'),
};
const validatedFields = CommentSchema.safeParse(rawInput);
if (!validatedFields.success) {
return { errors: validatedFields.error.flatten().fieldErrors };
}
// Simulacija upisa u bazu podataka
// await db.comment.create({ data: validatedFields.data });
revalidatePath('/blog/[slug]', 'page');
return { message: 'Komentar je uspješno dodan!' };
}
U ovom primjeru koristimo zod za validaciju podataka, što je standard u modernom TypeScript razvoju. Metoda revalidatePath je ključna za produkciju jer govori Next.js-u da izbaci keširanu verziju stranice i dohvati svježe podatke, osiguravajući da korisnik odmah vidi svoj novi komentar bez ručnog osvježavanja browsera.
Integracija s UI-jem pomoću React Hookova
U Next.js 16, rad s formama je znatno olakšan uvođenjem stabilnog useActionState hooka (prethodno poznat kao useFormState u eksperimentalnim fazama). Ovaj hook omogućuje lako upravljanje stanjem akcije, uključujući povratne informacije o greškama i status učitavanja. Za razliku od klasičnog useState pristupa, useActionState je dizajniran da radi sinkronizirano sa serverskim akcijama.
'use client';
import { useActionState } from 'react';
import { createComment } from '@/app/lib/actions';
export default function CommentForm({ postId }: { postId: string }) {
const initialState = { message: '', errors: {} };
const [state, formAction, isPending] = useActionState(createComment, initialState);
return (
<form action={formAction}>
<input type="hidden" name="postId" value={postId} />
<textarea name="text" placeholder="Vaš komentar..." className="border p-2" />
{state.errors?.text && <p className="text-red-500">{state.errors.text}</p>}
<button type="submit" disabled={isPending}>
{isPending ? 'Slanje...' : 'Objavi komentar'}
</button>
{state.message && <p className="text-green-500">{state.message}</p>}
</form>
);
}
Korištenje isPending varijable omogućuje vam da vizualno onemogućite gumb ili prikažete 'spinner' dok se akcija izvršava na poslužitelju. Ovo pruža trenutačnu povratnu informaciju korisniku, što je imperativ za dobar UX (User Experience).
Sigurnost u produkciji: CSRF i Autorizacija
Kada radimo u produkcijskom okruženju, sigurnost mora biti na prvom mjestu. Next.js automatski implementira određenu razinu zaštite od CSRF (Cross-Site Request Forgery) napada za Server Actions uspoređujući Origin zaglavlje s Host zaglavljem. Međutim, to nije dovoljno za aplikacije koje rukuju osjetljivim podacima.
Najčešća pogreška je pretpostavka da je Server Action sigurna samo zato što se 'nalazi na serveru'. Svaka akcija mora provjeriti autentifikaciju i autorizaciju korisnika. Ako imate akciju za brisanje posta, morate osigurati da korisnik koji ju poziva zapravo posjeduje taj post ili ima administratorska prava. Uvijek dohvaćajte session ID iz sigurnih HTTP-only cookieja unutar same akcije koristeći next-auth ili slične biblioteke, umjesto da šaljete korisnički ID kao skriveno polje u formi koje se lako može manipulirati.
Optimizacija performansi i keširanje
Jedna od najvećih prednosti rada s Next.js App Routerom je granulirana kontrola nad keširanjem. Kada Server Action promijeni podatke, često želimo osvježiti samo određeni dio aplikacije. Uz revalidatePath, na raspolaganju nam je i revalidateTag. Ovi mehanizmi omogućuju 'on-demand' revalidaciju koja je znatno efikasnija od postavljanja kratkog TTL-a (Time To Live) na cijelim stranicama.
U produkciji, visoke performanse se postižu i minimiziranjem količine podataka koji se šalju između klijenta i servera. Server Actions podržavaju slanje binarnih podataka (npr. uploade datoteka), ali treba paziti na veličinu payload-a. Ako vaša akcija procesira velike slike, razmislite o korištenju streaminga ili direktnog uploada na S3 uz korištenje Server Action-a samo za potpisivanje URL-a.
Rukovanje greškama i robusni Error Handling
U produkciji ne smijete dopustiti da se neobrađene iznimke (exceptions) 'ispucaju' do klijenta u obliku 500 Internih grešaka s potpunim stack traceom, jer to otkriva previše o vašoj infrastrukturi. Umjesto toga, svaka Server Action trebala bi biti unutar try-catch bloka koji vraća standardizirani objekt s greškom.
export async function updateProfile(formData: FormData) {
try {
// logika ažuriranja profilea
} catch (error) {
console.error('Logging to Sentry:', error);
return {
success: false,
message: 'Došlo je do neočekivane pogreške. Molimo pokušajte kasnije.',
};
}
}
Ovakav pristup osigurava da klijent uvijek dobije informaciju o tome što se dogodilo, dok se stvarna tehnička greška logira u sustave poput Sentryja ili Datadoga radi daljnje analize. Također, važno je razlikovati validacijske greške (400 Bad Request) od serverskih (500 Internal Server Error) kako biste korisniku mogli dati koristan savjet što popraviti.
Zaključak i budućnost razvoja
Next.js 16 sa Server Actions postavlja nove standarde u razvoju modernih web aplikacija. Ono što je nekad zahtijevalo sate postavljanja API endpointova, middlewarea i redux-saga ili react-query stanja za svaku sitnicu, sada se rješava unutar par linija koda uz potpunu Type-safety podršku. Iako je prag ulaska niži, kompleksnost koju donosi 'seamless' integracija klijenta i servera zahtijeva dublje poznavanje HTTP protokola i sigurnosnih principa.
Kao urednik portala BAJT, moj savjet za svakog developera je da prihvati ove promjene, ali s oprezom. Uvijek testirajte svoje akcije, koristite Zod za validaciju i nikada ne vjerujte podacima koji dolaze s klijenta. S pravilnom implementacijom, Next.js aplikacije postaju brže, održivije i lakše za skaliranje, što je u konačnici cilj svakog inženjera.
Komentari