Capítulo 79 de 456
Detalha o comportamento específico do Next.js para Server Actions (React Server Functions invocadas via <form action>, formAction, ou transição client-side): modelo de resposta em roundtrip único, dispatch sequencial, fronteira de segurança e integração com cache.
Promise.all no cliente não paraleliza Server Actions; paralelize dentro de uma única action, ou use Server Component/Route Handler.updateTag, revalidatePath, mutação de cookies via cookies(), e redirect incluem re-render na mesma resposta; revalidateTag com perfil stale-while-revalidate NÃO inclui (marca para refresh em background).serverActions.allowedOrigins.serverActions.bodySizeLimit.NEXT_SERVER_ACTIONS_ENCRYPTION_KEY estável em deployments multi-instância.updateTag: expira tag imediatamente, a próxima leitura (inclusive o re-render da própria resposta) espera dado fresco — use para read-your-own-writes. Server Actions apenas.revalidateTag: refresh stale-while-revalidate com cache-life profile — leituras seguintes recebem valor stale enquanto busca fresca ocorre em background; o próprio re-render NÃO espera.revalidatePath: invalida por path de URL, quando tagging é overkill para uma única rota afetada.refresh: reobtém o RSC Payload da rota atual sem invalidar cache — usar quando a view depende de estado fora do cache.'use server'
import { revalidatePath } from 'next/cache'
import { auth } from '@/lib/auth'
import { db } from '@/lib/db'
export async function createPost(formData: FormData) {
const session = await auth()
if (!session?.user) throw new Error('Unauthorized')
await db.post.create({
data: { title: String(formData.get('title')), authorId: session.user.id },
})
revalidatePath('/posts')
}
redirect não executaria (ele lança exceção), então revalidação deve vir antes.'use server'
import { auth } from '@/lib/auth'
import { db } from '@/lib/db'
// Safe: take only the change, derive identity from the session, look up by ownership.
export async function completeItem(itemId: string) {
const session = await auth()
if (!session?.user) return
const item = await db.item.findFirst({
where: { id: itemId, ownerId: session.user.id },
})
if (!item) return
await db.item.update({ where: { id: item.id }, data: { completed: true } })
}
Promise.all no cliente pra paralelizar Server Actions: o dispatcher do Next.js as serializa por cliente de qualquer forma; a paralelização precisa acontecer dentro de uma única action.id/ownership nele: validação de schema (zod) só checa forma, não posse — sempre re-derive ownership a partir da sessão.updateTag/revalidatePath/cookies() (set/delete)/redirect ganha re-render incluído na mesma resposta; revalidateTag (SWR) não.updateTag para read-your-own-writes imediato, revalidateTag para refresh em background, revalidatePath para invalidação simples por rota, refresh para reler estado fora do cache.NEXT_SERVER_ACTIONS_ENCRYPTION_KEY estável entre instâncias e trate "Failed to find Server Action" como caminho de retry na UI, não falha dura.NEXT_SERVER_ACTIONS_ENCRYPTION_KEY e considerações de multi-instância.updateTag/revalidateTag/revalidatePath/refresh.