A Beginner's Guide to Server-Side Rendering in ReactiveSearch

Improve page rank by converting your search UI to use server-side rendering

In this article, we share a step-by-step guide on how to convert a ReactiveSearch built UI into a SSR search UI, which is beneficial for SEO, caching, and user experience.

Why SSR a search UI?

To understand the importance of pre-rendering a web app, one needs to understand two mechanisms that can be used for rendering a web page, namely CSR and SSR.

Below are production applications of walmart.com rendered with SSR vs CSR.

We compared three of our applications(home, category, and search) in SSR vs CSR. These are the chrome network screen grabs of the pages being rendered. You’ll notice that SSR renders faster and that using CSR has a blank white page while loading. Most applications that use CSR will obviously replace the blank white page with a loading icon, but since we use SSR for our normal operations when forced into CSR mode, the pages are blank. Please note these are one-off captures, with our machines, at a certain time of day with the current prod build, so individual performance can vary-but this should be the general trend that you see for apps.

Here is the first server response for the home, category, and search pages. I would ignore the green bar because that is more relative compared to the rest of the network graph. The two things I want to call attention to are the document size and the TTFB. Since the server is responding with HTML for the page, you’ll notice the document size for SSR is always bigger. Another point that was talked about earlier, the CSR response is faster(except for the home page for some reason in this test).

I can’t stress enough though that these captures are variable based on application, latency, server, location, and a bunch of other variables, so they shouldn’t be taken as scientific fact, but more of a general trend.

What is Client Side rendering (CSR)

A React application consists of one HTML page, which is index.html, and to create other HTML content, we use JSX. JSX is first converted into plain JavaScript because browsers support only JavaScript. After that, JavaScript creates the HTML content and renders it on the user's screen. React moves all the content into one HTML file. This is known as Single Page Application, or SPA.

Problem with Client Side rendering (CSR)

  • Slow at First

    • The whole application is rendered on the client side by the browser. So due to this, rendering of our initial page will take some time. But after the first load, it becomes very smooth and user-friendly.
  • SEO problem (search engine optimization)

    • CSR requires a two-wave process for JS rendering and indexing in a browser, generally by Google.

    • The first wave requests the source code, crawls, and then indexes the presented HTML. But in CSR we don't have much HTML because it takes time to convert from JavaScript to HTML.

  • Caching Issue

    • Since the HTML is not available in the initial render, browsers cannot cache the HTML structure of the page.

    • One way to avoid this issue is to cache the JavaScript, but this may prove to be costly as JavaScript files can take up a lot of space in the browser's memory.

What is Server Side Rendering (SSR)

A server-side rendered application enables pages to load faster, improving the user experience. When rendering server-side, search engines can easily index and crawl content because the content can be rendered before the page is loaded, which is ideal for SEO.

So to render our pages much faster we can use Next.js (Framework for React), which renders our pages on the server side and give us pre-rendered HTML for our pages.

SSR + Reactivesearch

With Reactivesearch's Server Side Rendering support, you can handle the initial render when a user (or search engine crawler) first requests your app. To achieve the relevant results on an initial render, we need to pre-populate the redux store of the ReactiveSearch App.

ReactiveSearch provides an API that works with any SSR solution, The basic idea of SSR support for ReactiveSearch is to perform any necessary API calls to the search client and compute the initial state of the App, then rehydrate the client side with the initialState computed on the server-side.

ReactiveSearch offers SSR via getServerState(), a method that takes two params with second one being optional:

  • the first param of the function receives the App component ref and,

  • the second param [optional] receives the URL string or query param object(should be parsed) to respect the URL query string.

import { getServerState } from '@appbaseio/reactivesearch';

How to build

Here, we will go step-by-step and build our application. We’ll use Codesandbox.io to generate code at each intermediate step, making it easy to test

Things we will need

Let's start with a prebuilt ReactiveSearch UI developed using Next.js but still required configuration to SSR the search UI.

The starter app

Converting the above starter app into SSR is as easy as passing 2 props and writing 2-3 lines of code.

  • The initialState would be computed and passed to the client side to rehydrate the App tree.

  • To compute the initial state, Let's import getServerState from the library.

      import {
          //  ... other components imported
          getServerState
      } from "@appbaseio/reactivesearch";
    
  • In the case of Next.js, We would utilize getServerSideProps it to compute the initial state of our app on the server side. You may read about SSR using Next.js here.

      // src/pages/index.js
      // add the below snippet at the end of your page 
    
      function Main(props){
      // your app component
      }
    
      export const getServerSideProps = async (context) => {    
          const initialState = await getServerState(Main, context.resolvedUrl);
          return {
              props: { initialState },
              // will be passed to the page component as props
          };
      };
    
  • Finally, the computed state should be passed to the <ReactiveBase /> component.

      <ReactiveBase
          // ... other props
          initialState={props.initialState}
          // the contextCollector is another prop required for RS SSR
          // to do some magic internally
          // you should pass it without worrying about its source
          // we handle it for you
          contextCollector={props.contextCollector}
      >
      // ...
      </ReactiveBase>
    

Finally, you can now run the dev server and catch the SSR in action. Here is the final Codesandbox.

You can look at the code for this app at https://github.com/appbaseio/reactivesearch/tree/next/packages/web/examples/ssr

Summary

ReactiveSearch provides an API to support Server Side Rendering (SSR) which allows for API calls to the search client and the computation of the initial state of the App on the server-side. The initialState is computed and passed to the client side to rehydrate the App tree, and the dev server can be run to see the SSR in action.

Here comes the end of our journey, and we have got our awesome CLIENT-SIDE search app built with ReactiveSearch converted into an SSR search app. To summarize our journey:

Voila 🎉, We have finally converted our CSR search UI into an SSR search UI with just 2-3 lines of code.