My guess at how React Server Component(RSC) works internally

Before I dive into the source code of RSC(React Server Components), here is me trying to implement something similar to SRC. Later I could compare it to the real implementation and strengthen my understanding.

Before you read the post, I sugges you watch the intro video from React team, Iā€™ll try to mimic the demo there. Also the official React Server Comonents demo uses the official APIs from React, in our demo, we donā€™t use them.

Iā€™ll split the full journey into several milestones to make it easier to follow, all the code are on github & stackblitz.

1 - Issues of client-side rendering

see the full code on github PR

Letā€™s start with an app of client-side rendering.

Above is a React app that:

This approach is pretty standard, it should be fine, Iā€™ve been doing this way for a long time. But still there are some issues :

How can we improve ? Letā€™s first start with the dependency issue.

2 Manually split component into client part & server part

see the full code on github PR

To address the dependency issue, if we donā€™t parse the markdown on client, we have to parse it on server. This means we need to run PostDetail on server and somehow communicate the response with cilent.

Here is what we are going to do:

Since we know JSX is rendered to React.createElement() calls, which returns some JSON, we can easily serialize the response with some special cases like symbols and built-in components.

By above steps, we have a rough Server Component working for us.

We managed to

Open Chrome Dev Console to view the requests of /render.

This looks great, right? But it doesnā€™t support nested components though, we cannot do the same to PostList, how can we improve?

3 Render Client Components in Server Components

see the full code on github PR

We couldnā€™t move PostList to server because it renders <Link/> and <Link/> needs DOM api which means it must be a Client Component

We can do following to address this issue

With this we are able to move PostList to a Server Component, Hooray! See the lazily loaded JavaScript from demo below.

But it is even more tedious now with more .client and .server, how can we make it less painful?

4 Automatically build Server Components

see the full code on github PR

We see how tedious it is to manually manage the client part of server component.

After splitting two components, we can observe that the client part of both server components are almost the same, it is just a loader component that communicates with /render, we can merge them into one component.

Then we can modify the build scripts to do this automatically for us so that

Now after building, client code use /public, server uses /built, components have the same name across the folders, as they originally are.

Below is the new app, we can see it works totally the same as before but the code is much cleaner with out importing anything as ā€˜.clientā€™ or ā€˜.serverā€™.

5 Support nested Server Components & Suspense

see the full code on github PR

So far we couldnā€™t move page-level components List & Detail to Server Components because

Letā€™s tweak the code a little bit so that

With this new demo, we can see the Suspenses be rendered nicely.

We donā€™t want the /render to be called multiple times though, how can we improve?

6 Render Server Components and stream down response

With what weā€™ve learnt from How progressive hydration works, we can try streaming down the responses in one request!

see the full code on github PR

The code is not complex actually, with previous episodes it is pretty natural to come this far. Open the Chrome Dev console to see that there is only 1 /render call for each page navigation.

There seems to be some issues with streaming on stackblitz, so you cannot see the Suspense rendered properly, I suggest you clone the repo to try it out locally.

Summary

This is my guess at how React Server Componet works internally. We can see that it is more about the streaming, which we should rely on frameworks (Hello, Vercel!).

The code is actually not complex (well, a lot of tasks were undone though, like error handling .etc).

I hope it is not too far away from the real implementation. Anyway Iā€™ll figure it out soon, stay tuned!

Want to know more about how React works internally?
Check out my series - React Internals Deep Dive!

šŸ˜³ Share my post ?    
or sponsor me

ā® Prev: What is Progressive Hydration and how does it work internally in React?

Next: How do React Server Components(RSC) work internally in React? āÆ