Skip to main content

What is server-side rendering and how does it improve site speed?

· 13 min read

Server-side rendering (SSR) addresses the performance and search engine optimization issues of single-page JavaScript applications. In contrast to client-side rendering, it generates static content on the server before sending it over to the user’s browser.

Server-side rendering improves site speed and results in better Core Web Vitals scores. However, sometimes it can be difficult to implement and might also increase First Input Delay.

In this article, we’ll look into server-side rendering in detail. We’ll see how it works, what problems it solves, how it compares to client-side rendering, and what pros and cons it comes with.

An overview of single-page applications

Single-page applications (SPAs) are a web app architecture that appeared as an alternative to traditional websites and multi-page applications. SPAs, also known as client-side apps, became possible with the introduction of asynchronous JavaScript (AJAX), which makes it possible to update smaller parts of the user interface without reloading the full page.

Modern-day SPAs are often built with frontend UI frameworks such as React, Vue, and Angular. They consist of reusable JavaScript components fully rendered on the client side.

The main goal of this architecture is to make web apps similar to native mobile and desktop applications in terms of interactivity. As SPAs only have a single HTML page that fetches data from the server asynchronously, users can see updates instantly, without having to wait for the whole page to refresh.

How does client-side rendering work?

Client-side rendering (CSR) is the default rendering method for single-page applications.

In web development, rendering means the process of converting application code into interactive web pages. The page HTML is generated by a JavaScript engine. With client-side rendering, this is always done on the frontend. The browser then takes the generated HTML to visually render the page.

If you use client-side rendering, it’s the user’s browser that generates the entire app, including the user interface (UI), data, and functionality. No server is involved in the process, except to store the client-side code and data and transfer it to the browser.

As the following code example shows, in CSR apps, the HTML file only contains a blank root (often also named app) element and a script tag. The root element is populated by the browser that downloads and processes the JavaScript bundle to render all the other elements:

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>CSR</title>
</head>
<body>
<div id="root"><!-- blank --></div>
<script src="/bundle.js"></script>
</body>
</html>

Since the browser needs to download and run the whole application code before the content appears on the screen, the first page load is usually slow with client-side rendering (server-side rendering splits this process between the client and server).

As a result, users see a blank screen or loading spinner for a relatively long time. This leads to a poorer user experience and higher bounce rates (see Google’s discussion of how page load time impacts bounce rates).

Client-side rendering flowchart
Image credit: React PWA

Server-side rendering provides a solution to this problem.

What is server-side rendering (SSR)?

Server-side rendering, also known as universal or isomorphic rendering, is an alternative rendering method for single-page applications. SSR generates the static HTML markup on the server so that the browser gets a fully rendered HTML page. This is done by using a backend runtime such as Node.js that can run the JavaScript code to build the UI components.

Here’s an example HTML file, containing a simple newsletter signup form, that the browser could receive with server-side rendering. All HTML elements inside the root element were rendered on the server:

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>SSR</title>
</head>
<body>
<div id="root">
<div class="container">
<h2>Stay Updated</h2>
<form method="post">
<input type="email" name="email"
placeholder="Enter your email" required>
<button type="submit">Subscribe</button>
</form>
</div>
</div>
<script src="/bundle.js"></script>
</body>
</html>

As the browser doesn’t have to render the HTML, static content appears on the page faster with server-side rendering. However, the browser still needs to download and process the JavaScript file to add interactivity to the HTML elements. As a result, users will need to wait more before they can interact with the app, e.g. click buttons or fill input fields.

Faster-loading static content versus less time between content visibility and interactivity is a trade-off between server-side and client-side rendering — but more on that later.

Steps in the server-side rendering process

An SSR app processes the same JavaScript code on both the client and server side — this is why it’s also called universal rendering.

In brief, server-side rendering consists of the following steps:

  1. Client’s HTTP request – When the user enters the URL into the browser’s address bar, it establishes an HTTP connection with the server, then sends the server a request for the HTML document.
  2. Data fetching – The server fetches any required data from the database or third-party APIs.
  3. Server-side pre-rendering – The server compiles the JavaScript components into static HTML.
  4. Server’s HTTP response – The server sends this HTML document to the client.
  5. Page load and rendering– The client downloads the HTML file and displays the static components on the page.
  6. Hydration – The client downloads the JavaScript file(s) embedded into the HTML, processes the code, and attaches event listeners to the components. This process is also called hydration or rehydration.

Here’s how server-side rendering looks from the browser’s perspective. Note that the flowchart below starts with Step 4 when the browser gets the server’s response:

Server-side rendering flowchart Image credit: React PWA

Server-side rendering frameworks and tools

Popular frontend UI frameworks all have their own features that make it possible to write universal JavaScript code that also runs on the server side, respectively:

Processing server-side JavaScript also needs a backend JavaScript framework that runs on the Node.js server, such as Express.js or Hapi. These backend frameworks handle network requests, render the components on the server, and return the pre-rendered HTML to the browser. You can use them together with any frontend JavaScript framework.

There are also full-stack JavaScript frameworks for creating universal applications, such as Next.js for React or Nuxt.js and Quasar for Vue.

Pros of server-side rendering

Now, let’s look at the most important thing: the pros and cons of server-side rendering.

Note, however, that most of these advantages and disadvantages apply to different degrees. Their magnitude and impact will vary depending on the application structure, page weight, frequency of user interactions, and other variables.

To assess how much they apply to your app, you’ll need to measure your performance data in a reliable way and test different scenarios.

Better search engine indexability

These days, search engine bots can easily crawl static HTML, but they still tend to have problems with indexing JavaScript-generated content. Even though Google can now index synchronous JavaScript, JavaScript SEO is a complicated question with several drawbacks such as delays in JavaScript indexing.

As a result, client-side rendering is still considered risky from an SEO perspective. Put simply, if you want to rank high in search engines, server-side rendering is the better choice.

Faster initial page loads

As SSR apps pre-render HTML on the server, it takes less time for the browser to load content onto the screen.

However, note that while first-time visitors do experience faster initial page loads with server-side rendering, caching might change this result for returning users. If the frontend page doesn’t load any dynamic data from the server and all code is already cached, the browser only needs to render the page locally with client-side rendering.

Faster Largest Contentful Paint (LCP)

Largest Contentful Paint is one of Google’s three Core Web Vitals now included in its search ranking algorithm. It’s also the one that’s the hardest to pass for both desktop and mobile search.

LCP is a time-based value measured in seconds. A lower value means a better LCP score. As the largest content element (either an image or text block) is part of the static content your server pre-renders, SSR will display it faster on the screen.

Lower Cumulative Layout Shift (CLS)

Cumulative Layout Shift is another Core Web Vitals score tracked by Google. It measures the amount of unexpected change in the dimension and position of your content elements after the first page render.

With server-side rendering, the browser doesn’t have to go over the rendering process step by step, which typically results in fewer random layout shifts and, therefore, better CLS scores.

Fewer issues with social media indexing

Similar to search engine bots, social media crawlers also have issues with indexing JavaScript content. For example, Facebook’s Open Graph Protocol and Twitter Cards don’t support client-side rendering. So, if social media is important for your marketing strategy, server-side rendering can be the better choice.

Better for accessibility

As the server sends pre-rendered content to the browser, SSR apps are more suitable for people who use older devices with less powerful CPUs.

Server-side rendering is also a frequent recommendation for SPA accessibility as assistive technologies such as screen readers can’t always parse client-side JavaScript.

Cons of server-side rendering

Despite its numerous advantages, there are still some cases when SSR might not be worth the effort. Here are the most important drawbacks of server-side rendering.

Increased complexity

SSR increases complexity, which may or may not be worth it for you. You’ll have to write universal code that runs both on the server and client, take care of more complicated dependency management and caching, set up and maintain a server environment, find developers with the proper skillset, and more.

Obviously, this more complex architecture will be more expensive, harder to maintain and debug, and more prone to errors.

Potentially higher First Input Delay (FID)

First Input Delay is the third metric of Google’s Core Web Vitals. It’s also the one where server-side rendering might lead to web performance issues. FID is a time-based value measured in milliseconds. It shows how long it takes for the browser to respond to the user’s first interaction.

With server-side rendering, the browser displays static content faster (which leads to a better LCP), but it still needs time to hydrate the application. As a result, the app looks ready for interaction while the code is still being processed in the background. If the user tries to interact with the app during this period of time, there will be a delay in the browser’s response.

The extent of the first input delay depends on many things, including your app’s complexity, whether there are many interactive elements, the page weight, and others. For many SSR apps, first input delay won’t be an issue.

However, if you experience higher FID, you still don’t have to give up on server-side rendering, as there are ways to mitigate it.

For example, your UI can indicate to users that the app is not yet ready for input (e.g. you can hide or disable the buttons) so that they won't try to interact with it too early and, therefore, produce a high FID score. Alternatively, you can eliminate long-running blocking tasks by splitting up rendering into smaller chunks.

Less efficient caching

With client-side rendering, you can speed up your app by taking full advantage of browser caching. The initial page HTML is the same for all pages, so you can cache it and load it from a content delivery network (CDN) along with the JavaScript code.

With server-side rendering, the page HTML is different for each page, so it’s harder to cache this on a CDN. Users who load a page that hasn’t been cached on the CDN will experience a longer page load time.

Compatibility issues

There are several third-party libraries and tools that are not compatible with server-side rendering.

For example, at DebugBear, we recently started implementing server-side rendering for some of our components. Our frontend is written in TypeScript and imports CSS code for each UI component, which is then compiled by Webpack and served as a single JavaScript file.

However, on the backend, we use the standard TypeScript compiler rather than Webpack, so we had to switch from SCSS includes to Emotion, a CSS-in-JS library, to render these components on the server.

Even though nowadays compatibility issues are less of a problem than used to be, you still need to choose your dependencies carefully if you want to use server-side rendering.

Higher costs

As client-side apps don’t need a server, you can deploy them to a free or cheap static storage service such as Netlifly or Amazon S3. However, you’ll need to pay for a server or at least a “serverless” backend to deploy an SSR application, which means higher running costs.

Larger HTML size

SSR apps come with a larger HTML size because of the embedded hydration state.

This is not really an argument against SSR, just something to keep in mind as a potential risk if it’s implemented poorly. You can test your app for HTML bloat and other issues with our free HTML size analyzer tool.

Summary: Is server-side rendering better?

All in all, server-side rendering has a positive effect on page load times, SEO, social media support, and accessibility. On the other hand, client-side rendering can be cheaper, easier to build and maintain, and better for First Input Delay.

You don’t necessarily have to choose between these two options, though. There are hybrid solutions, too, which might work better for your application.

For example, you can use server-side rendering for pages important for SEO and client-side rendering for highly interactive pages. You can also set up dynamic rendering on the server to detect the client and serve a static version of your app to search engine crawlers.

To see how implementing server-side rendering impacts your site speed, you’ll need to monitor everything from page speed to Core Web Vitals scores.

With DebugBear, you can gain insight into your detailed web performance data, compare it against your competitors’ results, and run synthetic tests from multiple locations around the world — all from a single user-friendly dashboard that you can try for free.

DebugBear dashboard

If you’d rather stay with client-side rendering, we still have many web performance optimization tips that can help improve your Core Web Vitals, image rendering speed, React performance, and more.

Get a monthly email with web performance articles.