DEV Community

kol kol
kol kol

Posted on

I Benchmarked 3 Rendering Approaches — The Results Made Me Rewrite My Entire App

I Benchmarked 3 Rendering Approaches — The Results Made Me Rewrite My Entire App

Last month I ran a controlled benchmark on three rendering approaches for the exact same dashboard page. Same data. Same UI. Same hosting. Different architectures.

The results weren't just different. They were embarrassing.

The Setup

Identical dashboard: data table with 50 rows, 3 charts, navigation sidebar.

CSR (Client-Side Rendering):

  • Bundle: 482KB JavaScript
  • Time to Interactive: 1.8s
  • First paint: blank white screen for ~800ms

Legacy SSR:

  • Bundle: 315KB JavaScript
  • Time to Interactive: 1.1s
  • First paint: HTML arrives fast, hydration takes forever

Next.js 15 RSC (Server Components):

  • Bundle: 89KB JavaScript
  • Time to Interactive: 0.3s
  • First paint: nearly instant, charts stream in

That's a 5.4x reduction in JS bundle and a 6x improvement in TTI between CSR and RSC. Not marginal. Not "maybe in prod." Real numbers from a real app.

What Changed

The biggest shift wasn't technical. It was architectural.

With Server Components, the component tree is the server. The browser becomes a thin renderer that only receives interactive islands. You stop sending React's entire runtime to the client for pages that don't need client-side interactivity.

// This runs on the server. Zero JS shipped to client.
async function Dashboard() {
  const stats = await db.query('SELECT ...');
  const chartData = await analytics.fetch();

  return (
    <Layout>
      <StatsTable data={stats} />
      <Suspense fallback={<ChartSkeleton />}>
        <AnalyticsChart data={chartData} />
      </Suspense>
    </Layout>
  );
}
Enter fullscreen mode Exit fullscreen mode

The mental model flip: default to server, opt into client. Not the other way around.

The Migration Cost

I won't pretend it was free. Rewriting a CSR app to RSC took about 3 days:

  • Day 1: Identify client-only components (forms, tooltips, drag-and-drop)
  • Day 2: Convert data fetching to server components
  • Day 3: Add streaming and Suspense boundaries

But the performance gain was immediate and measurable. PageSpeed score went from 52 to 94. Core Web Vitals all green.

The Lesson

I'd been shipping hundreds of kilobyts of JavaScript because "that's how React works." It doesn't have to. The framework gave me the tools to send less code — I just had to change my mental model.

If you're still defaulting to 'use client' for every component, you're leaving performance on the table. Start server-side. Only cross the boundary when you genuinely need interactivity.

Your users' network connections will thank you.

Top comments (0)