Telerik blogs

Server Components are server-only React components that can generate the HTML from an individual component, not necessarily the entire app. Get a brief history and how other frameworks are handling it.

Server HTML Generation History

Perl

Some of the first great websites like Amazon, eBay and Yahoo used the Perl programming language to generate HTML on the server. Static websites were great, but often data was dynamic and needed to be updated on the fly.

When websites became large enough, text databases were transitioned to mySQL. Data was able to be loaded from the server dynamically. You could update a price, create a new post or add a new product without rebuilding your entire site.

However, it was difficult to connect HTML templating and Perl syntax together for a better developer experience despite templating tools like template toolkit.

PHP

PHP made templating easy in the late ’90s and early 2000s. I hated PHP because I felt that HTML should not be mixed with a programming language. This created a lot of potential problems, and was harder to debug. However, PHP’s syntax, speed and popularity were exponentially increased since WordPress adopted it to build a multibillion dollar empire. 70% of server-side websites still use it today.

Asynchronous JavaScript

Something changed with jQuery. While jQuery made browser compatibility problems easily disappear, it was Ajax (Asynchronous JavaScript and XML) that changed the game. Ajax allowed you to fetch HTML data from the server (technically XML), and refresh parts of your page with pure JavaScript. This meant no frames necessary, and your user experience was better. Eventually, we replaced it with fetch.

RPC, SOAP and REST

The idea of Remote Procedure Call (RPC) has existed since the ’70s. It basically servers as a way for a client to communicate with a server as if it were a local function. There are many different forms of this today.

When XML was still popular, people used Simple Object Access Protocol (SOAP) to communicate with their backends.

At some point, programmers realized returning JSON instead of XML is easier and faster, so the REST (Representational State Transfer) protocol became the go-to protocol. It is still used today on Node servers.

It is also worth mentioning GraphQL: while the communicate part works similar to REST, it is more accurately described as a Query Language and API runtime. To me, it is just another protocol.

Single-Page Application

Before Angular 1 and React, most dynamic websites primarily used the server to generate the HTML. However, the advent of the single-page application (SPA) showed a far better user experience compared to the multi-page application (MPA).

This basically means you load your JavaScript once, and your whole website is loaded. There is no wait time between loading pages. You just click, and it is there.

At first, there were only client-side applications. Client-side packages could get large quickly, and search engines can not read JavaScript.

Server-Side Rendering

Around that same time, in 2009, Node.js was created along with server-side rendering.

You could render your entire JavaScript application on the server and load it into the client by hydrating the data from the server to the client. This is basically just injecting the application state into the JavaScript and loading it. The bigger your website, the more you had to learn to lazy-load related portions (or just fetch them) so that your client-side package was not extremely large.

Generally speaking, your entire code is run two times (client and server), unless you separate your specific server data into endpoints. This is how Angular with Angular Universal still works today, although I suspect Angular 17 will change this.

File-Based Routing

A lot of core frameworks do not have a routing system at all. It is the meta-frameworks (Next.js, Nuxt, Remix, SvelteKit, etc.) that have a router. File-based routing allows you to create folders in your dev environment that correspond to specific routes in your application. A small number of people are against it, but I find it incredibly useful.

File-based routing is important because modern frameworks allow you to have a different route for server and client components. This means you can create a server route that loads the data, then injects that into an HTML page on the client.

This is accomplished using pure JavaScript functions like load or getServerSideProps, or you could emulate this in Angular with resolvers. So you will have one file that loads the data on the server, and another file that puts the data into the HTML file. It is important to note that the actual HTML is rendered on the server, and the data is hydrated on the client. File-based routing just makes this easier.

Thanks for the History Lesson, Nerd—What About RSC???

React Server Components do just that. They are server-only React components that can generate the HTML from an individual component, not necessarily the entire app, by returning jsx. You can have server components inside client components and vice versa. Logically this makes sense, but in practice you have to think about the mental model.

All components are server components by default, unless you use 'use client' in that part of your function. You really won’t even use RSC unless you have a meta framework that handles both server and client rendering well. As of today, Next.js is the adopter.

Imagine your app is one giant server component. You use JSX (or TSX if you’re smart) to create and build HTML. This is basically just using your Node.js server to generate HTML for you. Sound familiar? RSC is just PHP???

React Server Components (RSCs) have often been compared to PHP because of what PHP is still used for to this day. Most people who use Node.js are using it in combination with a JavaScript Framework. Maybe it is a full circle, but we are definitely not getting rid of client-side code.

But HTML is Already Generated on the Server?

Not exactly, but yes. If you generate HTML on the server and display it on the client, it is not reactive in server components, nor in PHP. That means you cannot use useState, useEffect or any other state management package to dynamically change your data after it is loaded.

In the past if we wanted to have interactivity, we would have to load the JavaScript in the header, which the client would use once the page loaded. Frameworks made this easy by injecting the script tags for us, and the data into the html page as JSON. But not everything is interactive.

Server Tree

In React, you have your React Component Tree that is loaded to the browser. This means everything can basically be interactive by default. According to Dan Abramov, React’s lead team member, you’re really just adding the ability to create a server tree on the server side different from the client tree. You don’t need access to the server tree on the client as it is not interactive. He goes into detail on the basic understanding in RSC From Scratch.

Rich Harris is Against It

Svelte’s creator is against Server Components, although I only partly agree with him.

https://youtu.be/uXCipjbcQfM?t=1568

1. Latency Spikes

Harris’ main argument is that when you have an unstable connection, like when you’re on a subway, the user experience will not be as good when using something like Server Components. You don’t want to redownload your app just to have interactivity like in the PHP days.

I think he is missing the point here. If you design your app so that the interactive parts do not have to be redownloaded, this won’t matter. You could also poorly design a SvelteKit app to lazy load the wrong items causing the same problems. RSC just gives you more control.

Are we over-correcting? I emphatically say no.

2. Source Maps

Source maps help with debugging in production environments by mapping your compiled code to the original code. Basically, there will be no source maps with RSC, making debugging that part of the app impossible. Ironically he used the Source Map example again to illustrate how leaking server only code to the client can be a problem. Do we want server source maps or don’t we, Rich!?

While I think this is a valid point, I think it is rare that you can’t get the important parts of debugging done in a developer environment. However, I am not creating a framework, so I really can’t argue against this.

RSC Speed

Jack Herrington claims the old method of generating server components, using the App Directory, is faster. Other people have run his test with similar results:

https://youtu.be/3Q2q2gs0nAI

However, as Theo points out, these tests are done on a local machine. This means you don’t get the speed performance that CDN and caching will give you.

Your local machine is not the same thing as a fast server environment. It is actually quite nuanced on whether or not you should use server components. Some situations will be faster without them.

However, even Herrington thinks the speed of RSC will improve over time, hopefully to be faster than the old Next.js App Directory in all cases. TBD.

What Other Frameworks are Doing

Vue

Nuxt has implemented their own version of Server Components from Vue.

https://www.youtube.com/watch?v=17zBODTpuoo

This seems to be in a slower development state than RSC, but the future will tell.

Colocation

It is also worth nothing that you may see colocation in some frameworks, which is backend code in frontend files. The code is written in a way to make it look as if you’re calling a server function in the client, when in reality it creates an endpoint. The norm seems to be using server$() to create them.

As you can imagine, Rich Harris is against this too due to endpoint security reasons, and it also invokes a meta or pseudo JavaScript that to execute them.

He mentions the security problem can be solved with CSRF protection and CSP primitives just like SvelteKit uses, so why not just get the other frameworks to add that as well (except when they want open endpoints).

My Conclusion

I don’t use React. I have built some complex apps myself to learn it, but ultimately it is not for me. However, I think Server Components are a good thing. Let’s just keep HTML that is non-interactive, loading once.

I think the Source Map issue will figure itself out over time, and I believe the latency issue is more of a design problem. You have to know when to use them.

I also think the colocation is a great idea because it makes the developer experience better. I personally do use SvelteKit, even though I don’t agree with everything Rich Harris says. The developer experience and user experience seem to be a winner in most cases.

Server Components are just another way to optimize your code in React, or any other framework like Nuxt. It is not as complicated as it seems, but it is also not PHP.

I love the idea, and I am ready for other frameworks to see its potential.


About the Author

Jonathan Gamble

Jonathan Gamble has been an avid web programmer for more than 20 years. He has been building web applications as a hobby since he was 16 years old, and he received a post-bachelor’s in Computer Science from Oregon State. His real passions are language learning and playing rock piano, but he never gets away from coding. Read more from him at https://code.build/.

 

 

Related Posts

Comments

Comments are disabled in preview mode.