• Blog
  • Docs
  • Pricing
  • We’re hiring!
Log inSign up
project logo

nmsilva

my-portfolio

Starter template for a markdown blog
Public
Like
my-portfolio
Home
Code
5
docs
4
posts
6
Layout.tsx
README.md
H
index.tsx
Environment variables
Branches
1
Pull requests
Remixes
History
Val Town is a collaborative website to build and scale JavaScript apps.
Deploy APIs, crons, & store data – all from the browser, and deployed in milliseconds.
Sign up now
Code
/
posts
/
react-server-components-one-year-in.md
Code
/
posts
/
react-server-components-one-year-in.md
Search
…
react-server-components-one-year-in.md
slug:
react-server-components-one-year-in
date:
Jan 15, 2026
readTime_en:
8 min read
readTime_pt:
8 min leitura
title_en:
React Server Components — one year in
title_pt:
React Server Components — um ano depois
excerpt_en:
We migrated part of Dragonboat to RSC last year. What worked, what didn't, and whether I'd do it again.
excerpt_pt:
Migrámos parte do Dragonboat para RSC no ano passado. O que funcionou, o que não funcionou, e se voltaria a fazê-lo.
tags:
React, Frontend, Performance

Context

At Dragonboat we have a large React codebase. Most of it is a classic SPA — client-side routing, Redux, REST API calls from the browser. Last year we started migrating our public-facing pages and some dashboard sections to React Server Components.

Here's my honest take after 12 months.

What worked well

Data fetching is genuinely simpler. Being able to await directly in a component, close to where the data is used, removes a lot of the boilerplate around loading states and effects:

async function RoadmapList({ teamId }: { teamId: string }) { const roadmaps = await db.roadmaps.findMany({ where: { teamId } }); return <ul>{roadmaps.map(r => <RoadmapItem key={r.id} roadmap={r} />)}</ul>; }

Bundle size dropped. Heavy dependencies (date libraries, markdown parsers, chart configs) that were previously shipped to the client are now server-only. Our initial JS bundle shrank by ~35%.

Waterfall requests are easier to reason about. With client components you'd fire multiple useEffect fetches that cascade. RSC makes the data flow sequential and explicit.

What didn't work

The mental model is genuinely hard to teach. The "which components are server vs client" question trips up everyone on the team. We've had bugs from accidentally importing server-only code into client components.

Interoperability with our existing state management is painful. Redux and RSC don't mix naturally. We ended up with a hybrid approach that feels awkward.

Error boundaries and loading states feel more fragmented. The Suspense + RSC combination works, but debugging a broken streaming boundary is not fun.

Would I do it again?

Yes — but only for the right parts of the app. RSC shines for read-heavy, data-driven pages. For interactive, stateful UIs, classic client components are still the right tool.

The migration isn't free, but the performance and DX wins on the right pages are real.

---pt---

Contexto

No Dragonboat temos uma grande codebase React. A maior parte é uma SPA clássica — routing client-side, Redux, chamadas REST API do browser. No ano passado começámos a migrar as nossas páginas públicas e algumas secções do dashboard para React Server Components.

Aqui está a minha opinião honesta após 12 meses.

O que funcionou bem

O data fetching é genuinamente mais simples. Poder usar await directamente num componente, perto de onde os dados são usados, remove muito do boilerplate em torno de loading states e effects:

async function RoadmapList({ teamId }: { teamId: string }) { const roadmaps = await db.roadmaps.findMany({ where: { teamId } }); return <ul>{roadmaps.map(r => <RoadmapItem key={r.id} roadmap={r} />)}</ul>; }

O bundle size diminuiu. Dependências pesadas (bibliotecas de datas, parsers de markdown, configurações de charts) que antes eram enviadas para o cliente são agora server-only. O nosso bundle JS inicial reduziu cerca de 35%.

Os waterfall requests são mais fáceis de raciocinar. Com componentes cliente, disparavas múltiplos fetches useEffect em cascata. O RSC torna o fluxo de dados sequencial e explícito.

O que não funcionou

O modelo mental é genuinamente difícil de ensinar. A questão "quais componentes são server vs client" apanha toda a gente na equipa. Tivemos bugs de importar inadvertidamente código server-only para componentes client.

A interoperabilidade com a nossa gestão de estado existente é dolorosa. Redux e RSC não se misturam naturalmente. Acabámos com uma abordagem híbrida que parece desajeitada.

Os error boundaries e loading states parecem mais fragmentados. A combinação Suspense + RSC funciona, mas depurar um streaming boundary partido não é divertido.

Voltaria a fazê-lo?

Sim — mas apenas para as partes certas da app. O RSC brilha em páginas orientadas a dados e de leitura intensiva. Para UIs interactivas e com estado, os clássicos componentes cliente continuam a ser a ferramenta certa.

A migração não é gratuita, mas os ganhos de performance e DX nas páginas certas são reais.

FeaturesVersion controlCode intelligenceCLIMCP
Use cases
TeamsAI agentsSlackGTM
DocsShowcaseTemplatesNewestTrendingAPI examplesNPM packages
PricingNewsletterBlogAboutCareers
We’re hiring!
Brandhi@val.townStatus
X (Twitter)
Discord community
GitHub discussions
YouTube channel
Bluesky
Open Source Pledge
Terms of usePrivacy policyAbuse contact
© 2026 Val Town, Inc.