Server Components vs Server-Side Rendering: A Comprehensive Guide
Get the project source code below, and follow along with the lesson material.
Download Project Source CodeTo set up the project on your local machine, please follow the directions provided in the README.md
file. If you run into any issues with running the project source code, then feel free to reach out to the author in the course's Discord channel.
This lesson preview is part of the Next.js Complex State Management Patterns with RSC course and can be unlocked immediately with a \newline Pro subscription or a single-time purchase. Already have access to this course? Log in here.
Get unlimited access to Next.js Complex State Management Patterns with RSC, plus 70+ \newline books, guides and courses with the \newline Pro subscription.
[00:00 - 02:37] Welcome to lesson 2 of the serial components module. In this video we're going to tackle a very common question when it comes to server components. Are they the same as server-side rendering? And let's be honest, given the basic definition that we tend to find online about server components, most developers tend to read it and assume that the way serial components work is exactly the same as server-side rendering, which it's also an excuse to just avoid server components altogether and go for SSR. However, as we're going to see in this video, they are not the same. Not only that, but there are many advantages of using server-side components over SSR, especially on very complex applications. So let's get going. So before we dive into how server components are rendered, quickly go over SSR or server-side rendering. So SSR renders pages on the server at request time, generating fully formed HTML, which then gets sent to the client. This is great for SEO, because your dynamic pages are also presented to the search agents as a static page, which has all the information the search engine needs to index it and then use it for search. So in the end, you get the best of both worlds. However, when SSR takes place, there are many steps that happen between the request landing on the server and you, as a user, seeing the page dynamically working. In fact, while this course is not about SSR specifically, and I will not go into detail about everything that happens there in the process, another simplification of it would include these four steps that you see here on screen. First, when the request reaches the server, your page is rendered statically on the server. That HTML then gets sent to the client, where the user is initially presented with a static version of your page. There is at the stage you're seeing your page, but there is no interactivity yet loaded. That's what happens next. In the meantime, while you see in this, the client, meaning the browser, is going to run React code that gets shipped with the page to essentially the process is called "hydrate your page." That means JavaScript is going to run and make sure that all the event handlers are set to make sure that the state is properly managed, essentially to set up the life cycle of all the components on the page.
[02:38 - 05:04] Once that is done, then you as a user are able to use the page or the app, essentially as intended, as originally intended in a dynamic way, interact with other elements, without you relating that anything happened. Those steps really go really fast, and you as a user will not notice that there is anything in between happening unless there are connection issues or that there are some problems during the iteration. Essentially, the problem and the reason why server components were created over SSR is that there is a lot of JavaScript that needs to be shipped to the client. I've already kind of mentioned this and hinted at this, but what happens if 90% of your page is actually static? You're still sending a lot of JavaScript to the client to essentially not do anything or do very minimal processing because the rest of your application doesn't really need it. That is when server-side components come into play. These components are rendered on the server, similar to SSR, but they have a unique ability to include server-side logic without sending any additional JavaScript to the client. That is because the server-side logic actually runs on the server. There is a very subtle difference here. When you write your components on an SSR architecture app, the code is not executed on the server. It is pre-rendered, the static version of your app is pre-rendered on the server, sent to the client, and then everything runs on the client. On the server-side components, the main difference is that your code actually runs on the server and what gets shipped is not the code, but rather the output of that code, the HTML generated by that single component. The backend will then stream in parallel those outputs, those individual server components to the client using what is known as server components payload. I kind of already mentioned this in previous videos, but essentially this payload contains three-measure things. The render HTML for your component, placeholders for the places where client components needs to be rendered. Remember that you can use client components inside server component.
[05:05 - 07:15] What's going to happen as we're seeing here is that the server component is going to be rendered on server, and wherever client component needs to be executed, because it can't really run on the server, it's going to be replaced by a placeholder, and then the client on the front end is going to stitch things together for you. And finally, the other thing that goes within this payload are props sent from the server into client components. We will see this in a future video, so I don't want to get into a lot of details right now, but keep this in mind because this is going to be one of the key methods that we're going to be using to solve or to answer that initial question of how to share state between server and client components. So the main differences are when and how the code runs. With SSR, scripts can still run client-side after the content loads. In fact, usually that's the case. There is no code executed on the back end. All the interactivity is loaded on the page, which is again known as hydration. Whereas for server components, there's no extra code needed on the client-side to run it, because the whole code already ran on the server. The only code needed is if you're mixing server and client components to again to stitch those two together once they're on the front end. Server components offer better performance due to less client-side JavaScript and really offload all the data processing and all the data fetching to the server, which is great for performance. They are a great option for heavy computation whenever one of your components has to deal with a lot of data or heavy prep processing so that you can later use the output of that for private API access. For example, whenever you have to keep whatever API you're using a secret from the user, then definitely server components are a great use case for that. And especially so when client-side interactivity is minimal.
[07:16 - 08:08] Again, if most of your application, if most of your page is static, then there is no reason to have a bunch of client-side components being hydrated and requiring a lot of boilerplate code on the client -side to get them to work. That code would not do anything. So instead through server components, you just ship the HTML and that's it. In summary, while SSR is great for SEO and definitely it's a great option for keeping the low time of your pages fast. Server components go a set farther to reduce the client-side bundle size and even enhance performance. They are a superior choice for static content generation with heavy server-side interactions. In the next video, we'll go over some ideal use cases for server components, but in the meantime, keep coding and I'll see you on the next one.