RSC: Back to the Server
Tags: react, rsc, javascript
Published: 2024-05-31 20:27:44

if you're like me and you've been keeping up-to-date in the React community over the past few months you've probably heard the acronym being talked about a lot. You might have played around with it in a framework (Next.js/Remix) or have a good understanding but are not sure of the applications, or you're curious about learning what it's all about.

In this article my aim is to share the ideas, motivations, and drawbacks, understand how it works and hopefully build a mental model for thinking about React Server Components.

If you're a React developer, you've probably worked with frameworks such as Next.js, Gatsby, etc. And commonly seen the acronym SSR (Server-Side Rendering) which is not to be mistaken for RSC. They have their similarities, but they are totally different. I'll explain using the famous lego pieces analogy.

Alright, let's say you have a box with all your Lego pieces, Eventually, you'll want to play with your Legos and will have to open the box, bring them all out and set up the pieces before you can start playing. This is how a default React app works. There’s an initial load time before it’s ready for use.

Now, with RSC your box has a special tool that puts together some of these pieces and they are ready for you to play. Instead of setting up your pieces from scratch (client), you have a tool (server) that sets up the pieces into ready-to-use parts and all you have to do is put them in their final positions.
 
One could argue that traditional SSR was present in early websites with a server-side language like PHP that could send entire web pages from the server on demand, and provides benefits such as SEO, less client-side loading, which improved initial load time, etc. However, one of the drawbacks with SSR is that after [hydration](https://react.dev/reference/react-dom/client/hydrateRoot) subsequent interactions with the app require making extra calls for dynamic components. 

Next, I'll share the motivation behind this new paradigm and the features and pain points RSC addresses.

### Motivation
The React team first announced the [RFC](https://github.com/reactjs/rfcs) for RSC (React Server Components) in [December 2020](https://www.youtube.com/watch?v=TQQPAU21ZUw), and by 2023, they announced the canary version for RSC.

**Performance & Speed**. Server components provides good performance "out the box"😉 which is one of the main pain points of a regular React app. It does this in different ways; 
 
It allows for the use of third-party packages on the server which could significantly reduce the bundle size of the app. For example, most commonly used packages such as date libraries(date-fns), utility library(lodash) etc could simply be eliminated if they're only needed in a specific RS Component.

```jsx
// Before Server Components

import lodash from "lodash"; // 71.5 (25.3k gzipped)

function TableComponent({text}) {
  // using some lodash functions
  return (/* render */);
}

```

```jsx
// With Server Components but zero bundle size

import lodash from "lodash"; // zero bundle size

function TableComponent({text}) {
  // using some lodash functions
  return (/* render */);
}
```

This is hugely beneficial for users and serves as a much better DX for developers.

**Shared Server-Client Context**. This could be the most impactful and useful application of RSC. When developing apps with React, you'll most likely have the need to interface with endpoints sending or receiving data to your app.
Early React has been client-focused, which led to the need to bring React to the server.  Developers often use different languages when writing code for both the client and server commonly PHP/Python and JS. The backend code is mostly responsible for accessing filesystems, database and external data sources. 


However, RSC clearly redefines this approach by eliminating the need for the API calls and the [request-response](https://en.wikipedia.org/wiki/Request%E2%80%93response) cycle. The boundary between the client and server has been streamlined by giving React fully access to the backend, the default mode allows for database calls, filesystem access, and passing props directly to components. Here's how an example server component accessing the filesystem would look:

**File System**

```jsx
import fs from 'fs';

async function Post({slug}) {
  const post = JSON.parse(await fs.readFile(`${slug}.md`));
  return <PostComponent post={post} />;
}
```

**Database Calls**

```jsx
import db from 'db';

async function Post({slug}) {
  const post = await db.findOne(slug);
  return <PostComponent post={post} />;
}
```
With server components, the security benefits of avoiding sending secret keys such as user tokens and API keys would also be hugely impactful as the client can access other necessary data without exposing crucial ones to the client.

**Developer Experience**. Think about how advantageous this could be in a typical production app where we have typed props defined in our client components and accept data from a server component. This approach allows for better developer experience and fully typed experience across client and server.

Firstly, simply opt-in the component as a client component using the `use client` [directive](https://github.com/reactjs/rfcs/pull/227).

```tsx
"use client"
// client component: client-component.tsx

export default function Author({
  authorName
}: {
 authorName: string;
}) {
  return (
    <div className="text-xl font-bold">
      {authorName}
    </div>
  );
}
``` 

```tsx
// server component: server-component.tsx
import db from 'db';

async function Post({id}) {
  const author = await db.findOne(id);
  return (
     <Author 
      authorName={author.name}  // would likely display an error when it's doesn't match type "string" specified in the client component
     />;
}
``` 


### Drawbacks
Just like all novel paradigms, there are some limitations to React Server Components.

**Adoption**. Demonstrating the full benefits of **React Server Components** with the _react_, _react-dom_ and _react-dom/server_ packages can be a lot for newbies, and even intermediate developers to wrap their heads around from routing to bundler configurations. So, it's important that there's a flexible and less boilerplate approach to adopting the full benefits of RSC. So far, the React team has partnered with the Next.js team to fully integrate RSC into the framework. Other Libraries and framework authors would learn from this approach as it's all open-source and could take a while before most of the API are fully standardised.

**Developer Education**. Introducing this feature in frameworks' latest releases and codebases across different projects and companies means more for developers to learn. This could mean new sets of questions in notable library repositories as issues, StackOverflow questions, and confusion around how to use and properly distinguish between server or clients components.


### Conclusion
The React Server Components approach could grow into a wide range of useful solutions in different aspects of web apps and possibly eliminate current painful ways of writing React apps. 

Possible applications: With the rise of generative AI (I tried my best to not include AI, but it's 2024), components could be specified to receive specific props, and different versions of the components could be rendered to users to enhance A/B testing. 

### Useful Links
[React Docs: Server Components](https://react.dev/reference/rsc/server-components)

[React Server Components RFC](https://github.com/reactjs/rfcs/blob/main/text/0188-server-components.md)

[Nextjs: Rendering](https://nextjs.org/docs/app/building-your-application/rendering)

[React For Two Computers](https://youtu.be/T8TZQ6k4SLE?t=18827)