React Server Side Rendering with Express

React Server Side Rendering with ExpressDaniel Lee Cher ChenBlockedUnblockFollowFollowingApr 28Photo by Dlanor S on UnsplashReact Server Side Rendering provides the ability to render your React pages from server such as ExpressJs.

React SSR provide various benefits which includes SEO Friendly and faster initial page load.

React has an amazing documentation on ReactDOMServer.

PrerequisitesCode Editor — I use Visual Studio CodeReactNodeJsExpressJsES6Some of the commands you see here are based on Terminal and I will try my best to include for Command Prompt (Windows)Let’s begin from scratchWe are going to build this React App from scratch as this will allow us to have more customization on our React App which you will understand later.

Don’t get me wrong Facebook make an great tool to provide a head start to React App creation and you don’t have to worry about the rest.

Read more here.

I am using NPM here, however if you prefer you can use Yarn.

Gant Laborde provided a NPM vs Yarn Cheat SheetCreate a directory for your code and from the directory executenpm initTo create our server, we are going to use ExpressJs.

Therefore we are going to include express into our modulesnpm install expressWe will be using ES6, therefore Babel is needed to transpile our code.

We need these dependencies for development only and not for production releasenpm install –save-dev @babel/cli @babel/core @babel/node @babel/plugin-proposal-class-properties @babel/plugin-transform-runtime @babel/polyfill @babel/preset-envThere are a bunch of dependencies we have here.

And they are@babel/cli — Allows us to compile from command line@babel/core — The core runtime@babel/node — Allow us to use babel instead of node.

@babel/plugin-proposal-class-properties — Transpile classes@babel/plugin-transform-runtime —To avoid duplication of files babel require.

@babel/polyfill — Needed when Promise is used@babel/preset-env — Allows the use of latest javascript without needed to manage the transformServer.

jsCreate a directory under the root directory and name it “src” and create a new file and name it server.

jsmkdir srctouch .

/src/server.

js #for terminalecho $null >> /src/server.

js #for windowsThis is a standard ExpressJs code nothing special here.

Compression middleware by ExpressJs is used to allow static content to be served with compression.

Make sure compression is part of you package by running npm install compressionapp.

use(express.

static(‘public’)); tell ExpressJs we are serving all static content via the public folderAs your React SSR app grows you will need to organize your route for easy maintainability.

With that, we create our route “/firstssr” which will reference to the route that we are going to create “ssr”RoutesWe will create a directory under “src” called routesmkdir .

/src/routes #for terminalmkdir /src/routes #for windowsNext create a new file and name it ssr.

jstouch .

/src/routes/ssr.

jsThroughout this tutorial we will add the SSR logic here.

For now we will keep it simple.

import express from "express";const router = express.

Router();router.

get("/", async (req, res) => {res.

status(201).

send("Hello World");});export default router;The above code simply allow us to browse to http://localhost:3030/firstssr and return a text “Hello World”Running the AppWe are going to run the app for the first time.

Before that we need to include some script into our package.

json.

Include the below under “scripts”"dev": "nodemon –exec babel-node src/server.

js"I used nodemon, if you do not have nodemon, feel free to install this package globally using npm install -g nodemonWe can now start our application using npm run dev .

Wait a minute, there is an error.

The reason for this error is due to a missing babel configuration as babel does not recognize import.

We need to add a babel configuration file.

To do so from the root directory create a file, name it .

babelrc and add the below{"presets": [["@babel/preset-env", { "targets": { "node": "current" } }]],"plugins": ["@babel/plugin-proposal-class-properties"]}Remember we added a couple for bebel dependencies earlier.

And one of them was @babel/preset-env and we are going to target it based on the current node version.

We also added a plugin to allow babel to transpile classes which will be needed later when we start to include our React component.

Let’s run npm run dev .

This time it executed without an issue.

Open your browser and browse to http://localhost:3030/firstssr and you should get the same result as the belowBuilding the React PageWe are going to build a very basic React page with a button that will calculate the length of the name.

Create a folder and name it “component” under the root folder or “src” and create a jsx filemkdir .

/src/componentstouch .

/src/components/app.

jsxGetting the React Component Rendered Server SideThe fun starts here.

We will now go back to our SSR route that we created (src/routes/ssr.

js).

React creates DOM and will append to the HTML.

This is exactly what we are going to do now.

We first need a HTML that will allow React’s DOM to be rendered onto.

The HTML can be from a remote server or a physical file.

Replace the existing router.

getrouter.

get("/", async (req, res) => {const theHtml = `<html><head><title>My First SSR</title></head><body><h1>My First Server Side Render</h1><div id="reactele">{{{reactele}}}</div><script src="/app.

js" charset="utf-8"></script><script src="/vendor.

js" charset="utf-8"></script></body></html>`;res.

send(theHtml);});Let me explain what is happening hereWe are using Handlebar as the template engine, alternatively you can you other view engine such as EJS or nunjucks{{{reactele}}} — This is a handlebar syntax of the variable “reactele”.

The content DOM rendered by React will be replaced here.

The 3 braces is to escape the HTML valuesThe 2 additional script — app.

js is the main React javascript that will be rendered and vendor.

js is simply any vendor script that we are going to use such as react.

I will cover this later under the Webpack configurationWhen we run our application with npm run dev we will get our HTML.

Next we will render our React DOM.

We need 3 dependency to make this happen.

npm install react react-dom handlebarsconst hbsTemplate = hbs.

compile(theHTML); is trying to compile the HTML we create into a Handlebar Template.

const reactComp = renderToString(<App />); is where React Server Side rendering works.

If you console log the “reactComp” you will see a bunch of HTML generated.

const htmlToSend = hbsTemplate({reactele: reactComp }); will be replacing the rendered React DOM into the handlebar variable {{{reactele}}}We got an error “Unexpected token at (23:35)” and we need to include @babel/preset-react the into “.

babelrc” under the presets setting.

Read more here.

Make sure this module is added as our dev dependency.

npm install –save-dev @babel/preset-reactAfter doing this, we can now run our application and the result is as belowYou will notice, nothing happen when you click the button.

If you have React Dev Tool installed, when you click the button it says “This page doesn’t appear to be using React”.

Why is this so?.We are rendering our React Component right?.I will explain in the next section.

Hydrating our React ComponentReact is a client side javascript.

It renders DOM and hydrate the component to get it working.

Because we only render our React component as HTML string and therefore, the current state of our application is just plain HTML.

A standard client side React application, we typically would have an entry point script and the code would be something similar to the belowReactDOM.

render(<yourreactcompoent />, document.

getElementByID('root');To hydrate the component, we will create a new file under components and name it index.

js.

import React from "react";import { hydrate } from "react-dom";import App from ".

/app";hydrate(<App />, document.

getElementById("reactele"));Remember when we generate our HTML we have a div called as “reactele”.

This is where we will hydrate our React component.

We are not done yet.

The last step is to configure the webpack.

Webpack will help us to build the entry point javascript and deployed it into public folder.

Webpack ConfigurationCreate a new file in the root folder of our app and named it “webpack.

config.

js”.

Here we have 2 entry point.

vendor — These will be the script that are from 3rd party such as React and they rarely changeapp — This is your React entry point that we just created on the previous sectionWe included babel-loader which will allow us to transpile our javascript with webpackAs build more complex app, you will be adding more routes with multiple entry point.

Why is this so?.By doing this, you can reduce the size of your app.

js and only load the needed React Component and not those component that is not needed.

You could also version and chunk your javascript with the webpack.

With the configuration done, we need Webpack to pact our javascripts.

Add a new script (webpack) in package.

json"scripts": {"dev": "nodemon –exec babel-node src/server.

js","webpack": "webpack -wd"},Before running our application, make sure you have included the webpack and babel-loader dependency by executing npm install –save-dev webpack webpack-cli babel-loader .

Webpack-cli is used to pack the scripts from terminal/command.

Running the AppFinally, we are going run our application.

We need to run 2 command and they are npm run webpack and npm run dev .

You should run these command in different terminal or command prompt window.

Once done browse to http://localhost:3030/firstssr and the resultCongratulation!.This is your first React Server Side Rendering!For the full source code, please go to my github React-SSR.

If you have any question, feedback or need help, feel free to contact me via linkedin.

.

. More details

Leave a Reply