The benefits of React server side rendering

Why server-side rendering React applications delivers important performance and SEO benefits.

A key technology underpinning the applications we develop is React as it offers many benefits. Providing great developer tools, and backed by a strong community, it boosts productivity and facilitates the process of writing and maintaining front-end components. Also, as React uses a Virtual DOM, the performance is vastly superior to a traditional JavaScript application. React is well suited to building large-scale applications with data that repeatedly changes. React provides a more natural creation of interactive UIs, a component-based structure, and much more.

However, it is essential to understand that React renders your application on the client-side, meaning that all JavaScript files and dependencies must be downloaded to the user’s browser before the page can start to be rendered by the browser. The fact remains that while React is extremely fast once the application is loaded, there is an increase in the initial load time (over vanilla HTML). Also, only some web crawlers can index the website or application.

Server-side rendering (SSR) aims to address these problems. In this article, I want to introduce you to SSR within React, the reasons to use it, and some popular frameworks for rendering React on the server-side.

Server-side and client-side rendering

Earlier web technologies like ASP.NET, PHP or Java, have always used a server-side approach. Whenever the user performs an action (such as a website search), the browser sends the request to the server, and the entire HTML page is generated on the server before being downloaded to the client. The issue, of course, is that this makes the overall user experience extremely slow as the user waits for each page to load.

By contrast, a React application pre-loads all pages and components to the browser, allowing it to respond immediately to the user’s action. The React application only needs to contact the server to fetch data that it has not previously loaded or cached.

The best of both worlds

With the introduction of server-side rendering to React, it is possible to get the best of both worlds. The initial page is rendered directly from the server, and the subsequent pages load directly from the client. The server-side rendering provides the user with a much faster initial page load, with React then handling all subsequent interactions, only contacting the server to obtain the data needed for future requests.

Performance benefits

Improved performance is a key benefit from moving to server-side rendering. SSR means there is no need for loaders or spinners for the initial load. The fully formed HTML page is sent down from the server on the first request and shown immediately without waiting for JavaScript files and dependencies to load.

Faster load times deliver a better experience for the end-user, and often result in increased conversion. The substantial performance benefits are one of the main reasons we recommend incorporating SSR for large and busy websites and applications.

SEO benefits

While Google and Bing can index JavaScript applications, it is still better to provide server-side rendered content ready for Google and other search engines to index. This is because the search engine crawlers will only wait a few seconds for the page to load. If the content is not yet loaded, then it won’t be indexed.

The advantage of SSR is that you get all the SEO benefits of a traditional HTML website since bots can now crawl the entire page. An app rendered with SSR can also be crawled by search engines that don’t execute JavaScript code - such as internal / enterprise search platforms which expect to index fully formed HTML pages.

Social Media

A similar benefit with SSR is that social media snippets and images are correctly shown when sharing an application page via social media. This is currently not possible when you just have a client-side rendered apps.

Accessibility

A further benefit is for accessibility, as server-side rendering ensures that screen readers can access the content.

Robustness

Finally, a server-side rendered page also provides a useful fallback as dependencies on JavaScript load are removed. The content will always be delivered regardless of browser or network connection issues.

Popular frameworks for rendering React on the server-side

While the benefits of server-side rendering are clear, it is essential to consider whether you need static rendering where all pages can be pre-rendered and generated in advance, or whether you need full server rendering, where every request is handled dynamically (as with a typical ASP.NET or NodeJS application)

Full server rendering is always slower than serving pre-rendered static HTML content. To support static rendering, you simply need to generate the HTML pages for every possible request ahead of time. For content-focused websites with limited personalisation, this is fine. But what if you’re building something where you can’t predict all possible requests, like a search engine? Or what if you need to incorporate user-generated content and the response changes on every request? In that case, you’ll need server rendering.

For static rendering, there are a variety of solutions. Tools like Gatsby aim to support scenarios where dynamic server rendering would typically be needed. Others, like Jekyl and Metalsmith, simply propose a template-based approach.

Navi

Navi is a JavaScript library for declaratively mapping URLs to asynchronous content. It comes with a static HTML generation tool that works well with React.

React-snap

Pre-renders a web app into static HTML. It uses a headless Chrome browser to crawl all available links starting from the home page. Uses best practices to get the best loading performance. It also provides the possibility to inline critical CSS to further improve load performance.

React-snapshot

An alternative to react-snap. A zero-configuration static pre-rendered for React apps. It provides the possibility to specify additional paths as entry points and exclude particular paths from being crawled.

Gatsby

Gatsby is a React-based Static Site Generator that has won the hearts of many with its exceptional UX (user experience) and DX (developer experience). Gatsby uses the JAMstack. The JAMstack is not about specific technologies. It’s a new way of building websites and apps that delivers better performance, higher security, lower cost of scaling, and better developer experience.

To be precise, it doesn’t do SSR at runtime. Instead, Gatsby does server-side rendering with Node.js at build time, where it creates static HTML, CSS, and JS when deploying the site. This leads to blazing-fast load times and has further optimisations such as route-based code splitting and prefetching.

Next.js

Next has SSR capabilities along with client application capabilities. It supports automatic code-splitting for faster page loads and client-side routing with optimised prefetching.

How we pre-rendered the Graph website

The Graph website is a static website where all content is public. As a result, the number of pages is predictable, the content is not drawn from a database, and the content will be static and the same for all users.

Gatsby was created specifically for such sites. It has simple options for creating and hosting a site. It separates the content from the design so that developers and editors can work similarly to CMS-powered websites, and everything will still be compiled as a site at build time.

Gatsby, it is excellent for out-of-the-box scenarios, but if you prefer to fine-tune the configuration, it isn’t the best option. Gatsby does not provide the possibility to configure public.html, web.config, or service workers. As we wanted to configure these, we decided to use react-snapshot. Also, the react-snapshot has pretty fewer dependencies then Gatsby.

The Graph website is hosted on Microsoft Azure as an Windows-based App Service. This allowed us to take advantage of the Microsoft Azure infrastructure, notably security, load balancing, and automated management. We also wanted to take advantage of the DevOps capabilities, including continuous deployment from Azure DevOps and GitHub, package management, deployment slots, and TLS/SSL certificates.

With react-snapshot rendering our pages as .html files, the only action we needed to take on Azure was to add a web.config file to rewrite the incoming server requests (e.g. https://graph.digital/product-development) to the physical .html files which have been rendered.

<?xml version="1.0" encoding="utf-8"?>
<configuration>
    <system.webServer>
        <rewrite>
            <rules>
                <clear />
                <-- rewrite to support server-side html page rendering -->
                <rule name="react route to static files" enabled="true" stopProcessing="true">
                    <match url="(.*?)/?$" negate="false" />
                    <conditions>
                        <add input="{DOCUMENT_ROOT}/{R:1}.html" matchType="IsFile" />
                    </conditions>
                    <action type="Rewrite" url="{R:1}.html" />
                </rule>
            </rules>
        </rewrite>
    </system.webServer>
</configuration>

Do you always need SSR?

The short answer is that ‘it depends’. Not all applications benefit from server-side rendering, especially apps that require authentication or provide users with a dashboard.

The expertise required for building a server-rendered React app is higher than an app initialised using create-react-app. In addition, the hosting considerations mean you might need to keep a server up and running.

Conclusion

Client-side rendered React apps are great but having apps rendered on the server does provide key benefits including performance, search engine visibility and social sharing.

I would highly encourage you to explore server-side rendering for your React apps and use it for your next product to see these benefits in action.