If you have had your hands on ReactJS, its won’t take a second thought to think of using react for any front project, whether it be a complex web app or even a simple website. But there is a catch, any client without javascript won’t be able to render the applications, which is not good for many circumstances especially SEO.

In this tutorial I will demonstrate how to Server Sider Render a reactjs application and to Integrate SSR into CI/CD. I will be using a react project build using Create React App with techstream demo template.

Live Demo

Let me explain the tasks and tools for the process in detail.

  • Server Side Rendering will be done using react snap.
  • To demonstrate CI/CD integration, will use Gitlab Pipelines and conventional method where build is done on local system and transferred to server.

Deployment will not be covered in detail here but I will brief on deployment to AWS S3 as part of CI/CD demonstration and also to a VPS server. For more on deployment check how to deploy react JS application

What is Server Side Rendering ?

Server Side Rendering  or SSR  means you pre-render the markup of a front-end framework on a back-end system before delivering to users. This means you server HTML with contents in them rather than an empty HTML file with a bunch of CSS and JavaScript (JS) links, and the browser processes the content.

A server side rendering can be achieved using 2 methods :

  1. Dynamic Pre-render: In here the markup is pre-render on server side as and when requested by user on serve before sending the content.
  2. Static Pre-render: In here the markup is rendered onto HTML file during build process, its also know as snapshot rendering. We will be performing this one.
Why do Server Sider Render ?

The main setbacks of front-end javascript frameworks is that the initial server response is generally an empty HTML file with a bunch of CSS and JavaScript (JS) links. These files need to be fetched in order to render relevant markup. This means

  • Extended load time, users need to wait until entire package is downloaded because the browser can only render markups after the download.
  • Clients without javascript support can only find empty pages.
  • No Search engine support.

Set up Static Generator

Lets start by adding react snap.

npm install react-snap --save-dev 

React snap uses puppeteer a node library which provides a high-level API to control Chrome (headless-chrome). This will be used for rendering the markup and creating snapshots.

Update the script section in package.json to run react-snap post app build.

"scripts": {
     "start": "react-scripts start",
     "build": "react-scripts build",
     "postbuild": "react-snap",
     "test": "react-scripts test --env=jsdom",
     "eject": "react-scripts eject"¸

If you are gonna run this on a container environments puppeteer (headless chrome) may fail due to sandboxing issues. To get around this, you need specify react snap to run puppeteer with --no-sandbox and --disable-setuid-sandbox.

Add this to package.json.

"reactSnap": {
    "puppeteerArgs": [

If you still get issues with puppeteer refer puppeteer troubleshooting.

If you use React 16+ ( mostly you are ) change index.js to use the hydrate().

import React from 'react';
import { hydrate, render } from 'react-dom';
import App from './App';

const rootElement = document.getElementById('root');
if (rootElement.hasChildNodes()) {
  hydrate(, rootElement);
} else {
  render(, rootElement);

That’s all you need to do, in terms of configuring.

Pre Render

To start the pre-render you can execute npm run-script build from your project root and you can see react-snap, the pre-render process will follow post build.

React JS SSR

The pre rendered pages will replace the build files created by react-scripts files in build directory. You can upload the directory to server and you have your server side rendered reactjs project.

Pre Render in CI/CD

Pre rendering in CI/CD is also straight forward and don’t need much change in configurations because the additional step of pre rendering is already defined in package.json.

You might need to update your docker images if any to include chromium-browser.

# Dockerfile
FROM ubuntu:18.04


# ---------------------------
# --- Install required tools

ENV DEBIAN_FRONTEND=noninteractive

RUN apt-get update -y && 
	apt-get install -y 

RUN apt-get clean

I am gonna be using the same settings and configurations I had used in React Js Deployment with small changes to a docker image with chromium because react snaps needs chromium package in the docker.

Gitlab repository for the Project : https://gitlab.com/anushbmx/react-js-ssr-deployment

Live Demo : https://demo.techstream.org/Server-Sider-Render-React-JS-Application/

Docker Image with Chromium : https://hub.docker.com/r/anushbmx/react-js-ssr-docker/

May the force of static files be with you.