Search⌘ K
AI Features

Server-Side Rendering (SSR)

Explore how server side rendering (SSR) works in Next.js, including its benefits like improved SEO and security, and its impact on performance and user experience. Understand when to use SSR and how to implement it using getServerSideProps for dynamic content.

Even though server-side rendering (SSR) sounds like a new term in the developer’s vocabulary, it’s actually the most common way of serving web pages. If we think of languages such as PHP, Ruby, or Python, they all render the HTML on the server before sending it to the browser, which will make the markup dynamic once all the JavaScript content has been loaded.

Well, Next.js does the same thing by dynamically rendering an HTML page on the server for each request, then sending it to the web browser. The framework will also inject its scripts to make the server-side rendered pages dynamic in a process called hydrationHydration is a process in which client-side JavaScript converts a static HTML web page into a dynamic web page..

Imagine we’re building a blog and want to display all the articles written by a specific author on a single page. This can be a great use case for SSR: a user wants to access this page, so the server renders it and sends the resulting HTML to the client. At this point, the browser will download all the scripts requested by the page and hydrate the DOM, making it interactive without any kind of page refresh or glitch. From this point, thanks to React hydration, the web app can also become a single-page application (SPA), taking all the advantages of both client-side rendering (CSR) and SSR.

Advantages of SSR

Talking about the advantages of adopting a specific rendering strategy, SSR provides multiple benefits over the standard React CSR:

  • More secure web apps: Rendering a page on the server side means that activities such as managing cookies, calling private APIs, and data validation happen on the server, so we’ll never expose private data to the client.

  • More compatible websites: The website will be available even if the user has disabled JavaScript or uses an older browser.

  • Enhanced search engine optimization: Since the client will receive the HTML content as soon as the server renders and sends it, the search engine spiders (bots that crawl the web pages) will not need to wait for the page to be rendered on the client side. This will improve our web app’s SEO score.

Limitations of SSR

Despite those great advantages, there are times when SSR might not be the best solution for our website. In fact, with SSR, we will need to deploy our web application to a server that will rerender a page as soon as it’s required. As we’ll see later, with both CSR and static site generation (SSG), we can deploy static HTML files to any cloud provider, such as Vercel or Netlify, for free (or at a meager cost); if we’re already deploying our web app using a custom server, we have to remember that an SSR app will always lead to a more significant server workload and maintenance costs.

Server-side rendering
Server-side rendering

Another thing to remember when we want the server side to render our pages is that we’re adding some latency to each request; our pages might need to call some external API or data source, and they’ll call it for every page render. Navigating between server-side rendered pages will always be slower than navigating between client-side rendered or statically served pages.

Of course, Next.js provides some great features for improving navigation performances.

Another thing to consider is that by default, a Next.js page is statically generated at build time. If we want to make it more dynamic by calling an external API, a database, or other data sources, we’ll need to export a particular function from our page:

JavaScript (JSX)
function IndexPage() {
return <div>This is the index page.</div>;
}
export default IndexPage;

As we can see, the page only prints the This is the index page. text inside a div. It doesn’t need to call external APIs or any other data source to work, and its content will always be the same for each request. But now, let’s pretend that we want to greet the user on every request; we’ll need to call a REST APIA REST API is an interface that two computer systems use to exchange information securely over the internet. on the server to get some specific user information and pass the result to the client using the Next.js flow. We’ll do that by using the reserved getServerSideProps function:

JavaScript (JSX)
export async function getServerSideProps() {
const userRequest = await fetch("https://example.com/api/user");
const userData = await userRequest.json();
return {
props: { user: userData },
};
}
function IndexPage(props) {
return <div>Welcome, {props.user.name}!</div>;
}
export default IndexPage;

Code explanation

In the preceding example, we used the Next.js reserved getServerSideProps function for making a REST API call on the server side for each request. Let’s break it down into small steps so that we can better understand what we’re doing:

  • Line 1: We start by exporting an async function called getServerSideProps. During the build phase, Next.js will look for every page exporting this function and make them dynamically server-side rendered for each request. All the code written within this function scope will always be executed on the server side.

  • Lines 2–8: Inside the getServerSideProps function, we return an object containing a property called props. This is required because Next.js will inject those props inside our page component, making them available both on the client and server side. In case you’re wondering, we don’t need to polyfill the fetch API when we use it on the server side because Next.js already does that for us.

  • Lines 10–12: We then refactor the IndexPage function, which now accepts a props parameter containing all the props passed from the getServerSideProps function.

When running this code, Next.js will always dynamically render our IndexPage on the server, calling an external API and showing different results as soon as we make changes in our data source.

Using browser APIs with SSR

As seen at the beginning of this section, SSR provides some significant advantages but has some caveats. If we want to use any component that relies on browser-specific APIs, we’ll need to render it on the browser explicitly because, by default, Next.js renders the entire page content on the server, which doesn’t expose certain APIs, such as window or document.