Course
Server-Side Rendering
Next.js Mastery: From Fundamentals to Full-Stack
Unlock the power of Next.js with this comprehensive course! Starting with the basics, you’ll learn essential skills such as routing, data fetching, and styling. Progress through practical projects, including building your own React Notes app, to gain hands-on experience. Dive into the source code to understand the inner workings and core principles of Next.js. Perfect for developers with a basic knowledge of React and Node.js, this course ensures you’ll be ready to create high-performance full-stack applications efficiently. Join us and master Next.js, backed by industry experts and a supportive learning community.
Server-Side Rendering
Server-side Rendering (SSR) was introduced in the previous chapter, "Rendering | CSR, SSR, SSG, ISR" and a demo based on Pages Router was provided:
// pages/ssr.jsexport default function Page({ data }) { return <p>{JSON.stringify(data)}</p>} export async function getServerSideProps() { const res = await fetch(`https://jsonplaceholder.typicode.com/todos`) const data = await res.json() return
}
From this example, we can see that SSR before Next.js v12 involved fetching data at the page level using methods like
getServerSideProps
. The data was then passed to each component as props, and the entire component tree was rendered as HTML on the server.However, HTML is non-interactive UI. After rendering the HTML on the server, the client still needs to download and execute the JavaScript to make the HTML interactive. This process is known as hydration. During this phase, the content becomes interactive UI.
From this process, we can identify several drawbacks of SSR:
- Data fetching for SSR must occur before component rendering.
- The component's JavaScript must be loaded on the client before hydration can begin.
- All components must be hydrated before any one of them can be interacted with.
This shows that SSR involves loading the entire page's data, JavaScript, and then hydrating the entire page in sequence. Any slow component can affect the overall performance.
Additionally, SSR only applies to the initial page load. It does not assist with subsequent interactions, page updates, or data changes.
RSC vs. SSR
Understanding these basic concepts, let's compare React Server Components (RSC) and Server-side Rendering (SSR). On the surface, RSC and SSR appear similar as both happen on the server and involve rendering content quickly. However, they are independent technologies. RSC and SSR can be used separately or together as complementary techniques.
As their names suggest, Server-side Rendering focuses on rendering, while React Server Components focus on components.
In simple terms, RSC provides a finer-grained approach to component rendering, allowing data to be fetched directly within components, unlike SSR in Next.js v12, which fetches data at the top level. RSC renders components on the server without including their dependencies in the bundle, whereas SSR bundles all component dependencies.
The biggest difference is:
- SSR renders components into HTML on the server and sends it to the client.
- RSC renders components into a special format called RSC Payload on the server, which is only sent to the client upon request for the relevant components. The RSC Payload includes rendered data and styles. The client uses this payload to rebuild the React tree and update the DOM.
This might sound abstract, but it's straightforward. Let's look at the React Server Components Demo:
When you open
localhost
, you see an HTML page similar to CSR with just a mount point. Clicking on the left-side Notes list sends a request to:http://localhost:4000/react?location={"selectedId":3,"isEditing":false,"searchText":""}
The response is:
This response contains the RSC Payload, which includes the data and fully rendered DOM structure. The client uses this payload to update the DOM without refreshing the page, enabling partial rendering.
This leads to the major difference between SSR and RSC: state retention. SSR generates new HTML pages each time, so state is not retained. RSC, however, produces a special format (RSC Payload) that can be re-fetched multiple times, allowing the client to update the UI without losing state.
Example of State Retention
In the example, we created a new note. The important part is that the previously expanded note in the left search result list remained expanded.
This comparison is between the RSC features shown in the React Demo and traditional SSR as represented by Next.js v12. Note that Next.js server components and client components are based on RSC but technically combine RSC and SSR for high performance.
Summary
In this chapter, we introduced and compared RSC and SSR. Although we did not cover specific Next.js implementations, understanding these concepts helps grasp the ideas of server components and client components in Next.js.
Let me know if you need further clarification or examples!