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.
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 :
- 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.
- 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": [
"--no-sandbox",
"--disable-setuid-sandbox"
]
}
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.
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
MAINTAINER Anush
# ---------------------------
# --- Install required tools
ENV DEBIAN_FRONTEND=noninteractive
RUN apt-get update -y &&
apt-get install -y
curl
git
expect
wget
zip
unzip
nodejs
npm
chromium-browser
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.