Introducing RSC Explorer: Demystifying React Server Components
Explore the inner workings of React Server Components (RSC) with RSC Explorer, an interactive tool designed to demystify the RSC protocol, streaming, server actions, and client-server interactions. Learn how React serializes and deserializes component trees directly in your browser.
Introducing RSC Explorer: Demystifying React Server Components
The recent surge in interest surrounding the React Server Components (RSC) protocol, particularly following the disclosure of a critical security vulnerability, has highlighted a need for clearer understanding. While an "implementation detail" of React, the RSC protocol is the serialization format for React trees—a superset of JSON—used by React's internal writer and reader. This design choice grants React immense flexibility for evolution and optimization, but it also means that even active RSC developers often lack an intuitive grasp of its underlying mechanics.
A few months ago, concepts related to the RSC protocol were explored in "Progressive JSON." While not strictly necessary for using RSC, understanding these internal workings can be both insightful and enjoyable. Inspired by this renewed interest, a new interactive tool called RSC Explorer is now available at https://rscexplorer.dev/. It is, of course, open source.
How It Works: A Guided Tour
As the adage goes, "Show, don't tell." RSC Explorer provides an embedded, interactive experience.
Let's begin with a "Hello World" example. Upon stepping through, you'll notice a yellow-highlighted line, such as <h1>Hello</h1>, represented as a piece of JSON within the RSC stream from the server. This is how React communicates with itself across the network. Pressing the "step" button reveals <h1>Hello</h1> appearing on the right, signifying the JSX that the client reconstructs after reading this line. This simple demonstration illustrates a JSX tag crossing the "network" and being revived on the client side.
It's important to note that RSC Explorer is a single-page application, running entirely within your browser (the server part operates in a web worker). Consequently, you won't see network requests in your developer tools. It functions as a simulation, yet it is built using the exact same packages React provides for reading and writing the RSC protocol, ensuring every output line is authentic.
Async Component: Witnessing Streaming
To observe streaming in action, consider a slightly more complex asynchronous component example. After stepping through twice, the upper right pane will display three chunks in the RSC protocol format. The right side shows what Client React has reconstructed so far. You'll notice a "hole" in the streamed tree, visualized as a "Pending" indicator.
React typically avoids displaying inconsistent UIs with "holes." However, by declaring a loading state with <Suspense>, a partially completed UI can be rendered. For instance, <h1> might be visible while <Suspense> displays fallback content because <SlowComponent /> has not yet streamed in. A final "step" will fill this "hole."
Counter: Sending Code to the Client
So far, we've focused on sending data. Now, let's explore sending code. Using the classic counter example, stepping through reveals something intriguing in the protocol payload. Instead of transmitting strings like "Count: 0" or raw <button> elements, the server sends <Counter initialCount={0} />—the "virtual DOM" itself. This can, of course, be transformed into HTML later, just like any JSX. It's akin to returning React trees directly from API routes.
Notice how the Counter reference transforms into ["client",[],"Counter"] within the RSC protocol. This instructs the client to "grab the Counter export from the client module." In a real framework, a bundler handles this process, which is why RSC integrates closely with bundlers, much like reading from a webpack require cache (a method RSC Explorer also employs).
Form Action: Client Referring to Server Code
Having seen the server refer to client-exposed code, let's reverse the dynamic: the client referring to server-exposed code. Here, greet is a Server Action, exposed as an endpoint using 'use server'. It's passed as an async function prop to a client Form component.
After stepping through three times, you can enter your name in the Preview pane and click "Greet." The RSC Explorer debugger will "pause," indicating that the greet Server Action has been triggered by a request. Stepping once more will reveal the response returned to the client.
Router Refresh: Frameworkless RSC
RSC is often taught within the context of a framework, which can obscure its core mechanisms. How does a framework refresh server content? How does a router operate? RSC Explorer offers a view of frameworkless RSC. While there's no router.refresh, you can implement your own refresh Server Action and a Router Component.
After repeatedly stepping to render the initial UI, observe the ticking timer. The ColorTimer component from the server passes a random color to the Timer component on the client, essentially returning <Timer color="hsl(96, 70%, 85%)" />. Now, press the "Refetch" button below the timer. Stepping through the server response reveals the continuously ticking Timer receiving new props from the server, changing its background color while preserving its internal state.
This process resembles refetching HTML with tools like htmx, but it's a standard React "virtual DOM" update, which avoids destroying client-side state. This technique, combined with URL matching and nesting, forms the basis of how RSC frameworks handle routing—a truly powerful example.
What Else Can You Explore?
For those eager to delve deeper, RSC Explorer provides additional examples:
- Pagination
- Error Handling
- Client Reference
- Bound Actions
- Kitchen Sink
- And, notably, the infamous: CVE-2025-55182 (requires selecting version 19.2.0 in the top-right corner to function).
The creator encourages the community to contribute more cool RSC examples. RSC Explorer allows embedding snippets on other pages (as demonstrated in this post) and generating sharable links, provided the code size remains within URL limits. The tool is entirely client-side, a design choice made for simplicity.
You are welcome to browse its source code on Tangled or GitHub. As a hobby project, specific promises aren't made, but it aims to be a valuable resource.