React Server Component, or RSC, was first introduced over three years ago, but is still confusing a lot of us web developers. We know React. We know server. We know component. But somehow putting them together isn’t what React Server Component seems to be.
As a user of React, I’ve been trying to wrap my head around RSC, too. And the following is what I’ve come to on a conceptual level.
I believe it helps to start with the big picture, and that big picture is called React architecture in which React fully controls a UI app beyond what we know as the client side (i.e. on browser). Any UI app that adopts this new architecture is said to be “fully built with React.” React architecture consists of two parts, React Server and React Client. They form a pair, i.e. React Server responds to requests from React Client. There’s an important caveat here: what makes them a server and a client is this request-response relationship, not necessarily where the process for each runs.
Before going further, let’s recall that React is all about Component. In React, Component refers to a certain recipe for a piece of UI. Following the recipe with the same values for its ingredients (e.g. props) should result in the same UI. In practice, each Component is a function that returns a React node. By composing Components into a tree, we create a recipe for a larger, more complex UI. A React app is then a root Component (that often has many nested children Components) we give React to build UI from.
What is React Server? It is a process that takes the full React Component tree and executes them Components unless marked with
"use client" to defer their execution. Its output is a mix of executed and not-yet-executed Components that can be sent to React Client. In turn, React Client is more or less what we have always known as React. Not much has changed except it knows how to finish the React tree by picking up where React Server has left off. Then it consumes the final React tree by either generating static HTML (i.e. Server Side Rendering or SSR),1 or attaching it to DOM on browser.2 The order is important here—for a given React app, React Server first sees the full Component tree, executes Components not marked with
"use client", and outputs a partially completed React tree. React Client only comes later to finish the job.
So conceptually, there is nothing really special about React Server Components as such. They are just Components that happen to get executed by React Server. The key difference between RSCs and React Client Components lies in not what they are but rather where and when they’re executed—and consequently the computing environment they have access to during execution.3 For example, if a Component is executed by React Server running on Node.js, it can access Node.js API. If a Component is executed in a computing environment with file system, it can read from and write to it. If Component is executed in an environment where a database is also available, it can query the database. And so on… On the other hand, the good old React Components being executed by React Client on a browser can access browser API. It’s the same idea: Components have access to APIs and resources available to where they get executed.4
In short, React Server Component is best understood as React Server + Component, not React + Server Component.
SSR also outputs initial data to recover the original React tree on browser so that it matches the generated HTML. This process is called, of course, hydration. ↩
React Client on browser also has a runtime that responds to browser events by re-executing Components and reconciling the resulting tree with DOM to keep the UI reactive. ↩
Because of this, I think alternative suggestions on what S in RSC should be (serialized, static, etc.) misses the point. ↩
React Client for SSR is a bit of an oddball here—it’s limited on both ends. It doesn’t allow Components to access the environment where the SSR process runs; it also cannot provide Components with the browser API because, well, the SSR process isn’t running on browser. ↩