AI Features

Why Server Components Exist

Learn about why traditional React apps ship too much client JavaScript and how Server Components change the mental model by letting the server render and stream serialized UI while the client focuses on interactivity.

For most of React’s history, we’ve treated the browser as the default place where application logic runs. In practice, that meant a common pattern:

  1. The server sends some initial HTML (maybe via SSR).

  2. The browser downloads the JavaScript bundle.

  3. React hydrates the UI to “wake up” the UI.

  4. Only then do we fetch data, rebuild state, and render the real UI.

This workflow carries an implicit rule: if something appears on the screen, the code to produce it must also run in the browser. That rule sounds reasonable, until you look at what modern apps actually do. A large part of most pages is not interactive: dashboards that list records, product pages that format content, article feeds, profile headers, tables, and “read-only” UI that mainly reads data and turns it into markup. Yet we still ship the same data-fetching and formatting logic to the client, even though the server can already handle that work.

As apps grow, the cost becomes obvious. Bundles include more “non-interactive” code, startup work increases, and users wait while the browser downloads, parses, and executes JavaScript whose main purpose is simply to fetch data and produce HTML, work that the server could have completed before sending the page.

To reduce this cost, we adopted techniques like code splitting, prefetching, and server-side rendering (SSR). These help, but they still optimize around the same underlying constraint rather than removing it. SSR improves first paint, but it can duplicate work: the server renders the UI, and then the client reruns component logic during hydration to make the app interactive. Over time, rendering, data access, and interactivity became tightly coupled, even in parts of the UI that never needed to be interactive in the first place.

React Server Components (RSC) exist because that coupling isn’t fundamental. The key shift is simple: Rendering UI doesn’t have to imply client-side execution. We can keep interactive code in the browser, while moving non-interactive rendering and data access to the server, reducing bundle size and avoiding unnecessary client work.

Server-first rendering with selective client hydration
Server-first rendering with selective client hydration

The above diagram depicts a React component tree split across environments. Upper-level components execute on the server, where data fetching and non-interactive rendering occur. Their output is serialized and streamed to the client as part of the render result. Within this tree, specific components are marked as client boundaries. Only these client components and their dependencies are sent to the browser and hydrated. The rest of the tree never becomes client-side JavaScript.

Why does client only rendering become expensive?

Server Components exist to separate what React renders from where that rendering logic runs. Traditionally, every React component implied client-side JavaScript, regardless of whether it handled user interaction or simply transformed data into UI. This forced the browser to ...