How to Implement Server Side Rendering in React

ssr in react

In the previous blog, we have already discussed why server-side rendering is important, and why I migrated from the react js app to next Js. If you haven't read that blog, I'll recommend to first read the blog from here - Why I Migrated Create React App to Next.js.

Now since react is one of the most favorite languages and is being used by many, so in this article, we will learn how we can achieve server-side rendering with react js.

For server-side rendering, the server 's response to the browser is the page's HTML ready for rendering so that the browser can start rendering without waiting for all of the JavaScript to be downloaded and executed. In client-side rendering, there is an empty page while the browser downloads and executes the JavaScript and other assets needed to render the page.

Lets start with the steps which you have to follow while creating the react app for server-side rendering.

Step 1. Create a New React App

So create react app is an officially supported way of creating a single page react application. It lets you to focus on the code rather than build in tools.

To create a project called ssr-demo, run this command:

npm init react-app ssr-demo

By now a directory called ssr-example must have been created inside the current project which contains the initial project structure with all the transitive dependencies being installed.

Navigate to the ssr-demo directory

cd ssr-demo

Finally, to check the installation, we launch our new client-side app :

npm start

You will see a sample create app on your browser at http://localhost:3000/. Now lets create a <Content> component inside the src directory.

src/Content.js

Now lets add some code to it, so that we can check on browser what is rendered.

copyimage
import React from 'react';
function Content() {
    return (
      <div>
        <h1>Server Side Rendering in React JS</h1>
        <img src="/logo512.png" className="App-logo" alt="logo" />
      </div>
    );
}

export default Content

This creates the <h1> heading with the react logo. Now lets render the <Content> in our <App> component. Open App.js file

src/App.js

Now replace the existing code with the code given below.

copyimage
import React from "react";
import "./App.css";
import Content from "./Content";

function App() {
  return (
    <div className="App">
      <Content></Content>
    </div>
  );
}

export default App;

Lets see on the browser what is rendered in the page view source. Navigate to your browser, right click and select View Page source(Ctrl + U). Now you might notice that <div id="root"></div> is empty since by default react is a client side rendering app.

client side rendering

Now we will start our server side changes to make this render on server side, first let us make another change in our index.js file in the src directory.

src/index.js

Now replace the existing code with the code given below.

copyimage
import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import App from './App';
import * as serviceWorker from './serviceWorker';

ReactDOM.hydrate(
  <React.StrictMode>
    <App />
  </React.StrictMode>,
  document.getElementById('root')
);

serviceWorker.unregister();

We will now create an express server and will render our <App> Component.

2. Create an Express Server which will render our App Component

Next, we will implement server-side rendering with react so that we can send fully generated HTML to the browser. To get started, we will install Express, the Node.js server side application framework:

npm install express --save

Create a new folder called server next to the src directory.

mkdir server

Create a new file server.js file inside server folder which will contain the Express server Code.

server/server.js

Add the following code in your server.js file

copyimage
import React from "react";
import express from "express";
import path from "path";
import fs from "fs";

import ReactDOMServer from "react-dom/server";

import App from "../src/App";

const PORT = process.env.PORT || 8080;
const app = express();

app.use("^/$", (req, res, next) => {
  const appcomponent = ReactDOMServer.renderToString(<App />);
  fs.readFile(path.resolve("./build/index.html"), "utf-8", (err, data) => {
    if (err) {
      console.log(err, "Something went wrong");
      return res
        .status(500)
        .send("Server responsed with some error, kindly check");
    }
    return res.send(
      data.replace(
        '<div id="root"></div>',
`<div id="root">${appcomponent}</div>`
       )
    );
  });
});

app.use(express.static(path.resolve(__dirname, "..", "build")));

app.listen(PORT, () => {
console.log(`SSR running on port ${PORT}`);
});

After creating-react-app by convention, the app is stored in the src / App.js file. This component will be loaded and rendered to a string using ReactDOMServer.renderToString(), which is supported by react-dom.

You get the contents of the ./build/index.html file, and replace the

placeholder, which is the tag where the application hooks by default, with `
${ReactDOMServer.renderToString(<App />)}

All information within the build folder will be provided as-is, statically, by Express.

All the Node.js code needs to be transpired by Babel, because the Node.js server-side code does not know anything about JSX or ES Modules.

npm install @babel/register @babel/preset-env @babel/preset-react ignore-styles

ignore-styles is a Babel utility that will tell it to ignore CSS files imported using the import syntax.

Let’s create an index.js file inside the server folder which will be our entry point and paste the code below.

copyimage
require('ignore-styles')

require('@babel/register')({
  ignore: [/(node_modules)/],
  presets: ['@babel/preset-env', '@babel/preset-react']
})

require('./server')

Now lets install nodemon that helps node js based application by automatically restarting the node application when file changes in the directory.

npm install nodemon

Server Side code is being completed and now its time to run the script from package.json to check if our application is being served from the server.

In the package.json file kindly add one npm script given below in the script object.

"dev": "npm run build && nodemon server/index.js"

Now we can easily build our client-side app bundle and transpile the server code, and start up the server on PORT 8080

npm run dev

Open the browser at port 8080 and you will see your server side rendered application.

Last time when we navigated to view page source we saw that <div id="root"></div> was empty, now lets check again if the source code is being served server side or not.

<div id="root"><div class="App" data-reactroot=""><div><h1>Server Side Rendering in React JS</h1><img src="/logo512.png" class="App-logo" alt="logo"/></div></div></div>

The server-side rendering has successfully translated the < App > component to HTML.

Conclusion

In this tutorial, we have learned how we can achieve server-side rendering with react. This is just a small example which is good for beginners.

Server Side Rendering gets complicated once we introduce routing, data fetching, or redux. We will learn more about them in future blogs where we will render a large react application server side which includes routing, data fetching and redux.