Pular para o conteúdo
Kayro Gomes
Frontend,  Reflexões

Server Components no Next.js 15: o que mudou na prática

Author

Kayro Gomes

Date Published

Imagem ilustrativa de exemplo usada em posts do blog

Texto opinativo: o que vem a seguir é minha leitura depois de 6 meses com Next.js 15 em produção. Se discordar, me chama no GitHub Issues do projeto.

O que mudou de verdade no 15

Muita gente ainda acha que React Server Components é "o Next faz a query no servidor". Não é — é mais profundo. RSC muda o que conta como estado, o que conta como fetch, e o que conta como "render". Server Components rodam uma vez no servidor e enviam uma árvore serializada pro browser, sem JS hidratado desnecessário.

No 15, três mudanças foram sentidas de verdade no meu dia a dia:

1. async params e searchParams

Não é mais um objeto — é uma Promise. Toda página que recebia slug agora precisa de await. Parece pequeno, mas simplifica a coexistência com Suspense e elimina uma classe inteira de bugs onde devs tentavam tratar params como síncrono e quebravam em produção.

1type Args = {
2 params: Promise<{ slug: string }>
3 searchParams: Promise<{ [key: string]: string | string[] | undefined }>
4}
5
6export default async function PostPage({ params, searchParams }: Args) {
7 const { slug } = await params
8 const { ref } = await searchParams
9 const post = await getPostBySlug(slug)
10 return <PostArticle post={post} ref={ref} />
11}

2. fetch cache mudou de default

fetch() em Server Components agora é cacheado por padrão, não no-store como era no 14. Isso é uma grande mudança: significa que chamar a mesma URL duas vezes na mesma renderização não dispara duas requests. Para o Payload, isso ajudou muito — múltiplas queries no mesmo post reaproveitam a cache.

3. Server Actions ficaram estáveis

Actions para mutação via form direto no server, sem API route, sem JS no client. O caso de uso que me pegou: o formulário de contato deste site. Antes: API route + fetch no client + loading state + error handling. Agora: <form action={submitContactForm}> e o Next faz o resto.

1// app/(frontend)/contato/page.tsx
2async function submitContactForm(formData: FormData) {
3 'use server'
4 const submission = await payload.create({
5 collection: 'form-submissions',
6 data: {
7 form: contactFormId,
8 submissionData: Object.fromEntries(formData),
9 },
10 })
11 revalidatePath('/contato')
12 redirect('/contato?enviado=1')
13}
14
15export default function ContatoPage() {
16 return (
17 <form action={submitContactForm} className="space-y-4">
18 <input name="full-name" required placeholder="Seu nome" />
19 <input name="email" type="email" required placeholder="Seu e-mail" />
20 <textarea name="message" required placeholder="Sua mensagem" />
21 <button type="submit">Enviar</button>
22 </form>
23 )
24}

O que ainda me incomoda

O debug de Server Components ainda é pior que Client Components. O error stack aponta para o arquivo compilado, não pro source. A mensagem de erro às vezes esconde a query que falhou. Tudo melhor que em 2023, mas ainda me faz perder 30 min por semana.

Foto de capa ilustrativa com gradiente azul e roxo — usada no hero da home

Imagem de capa ilustrativa. Substitua no admin em Mídia.

Server Components são o futuro do React web. Ainda tem fricção (debug, error messages, curva de aprendizado), mas os ganhos em performance e DX são reais. Se você está começando um projeto novo em 2026, RSC não é mais opcional — é o caminho padrão.