Server-side rendering in React

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<link rel="shortcut icon" href="/favicon.ico">
<title>My React app</title>
</head>
<body>
<div id="root"></div>
<script src="/app.js"></script>
</body>
</html>

Why is that a problem?

  • Slow internet connection might not load app.js quickly enought to have a good user experience
  • Slow devices, like older smartphones might not have the fastest loading times on the javascript code
  • Search engines and social networks might not recognise & find your website content as it is being loaded in client-side

How to solve this problem

1. Having your key pages static

2. Generate parts of your application as HTML pages when running the build process

"build": "webpack && react-snapshot --build-dir static"

3. Create a server-side rendered application in JS

Create your own custom SSR solution

yarn add express babel-node pug --save-dev
  • Express is the most popular webserver for node.
  • babel-node is a wrapper for node, which allows it to perform code transpilation on the fly
  • pug is a templating engine we can use with express.
<!doctype html>
<html>
<head>
<meta charset="utf-8" />
</head>
<body>
<div id="root">!{app}</div>
<script src="bundle.js"></script>
</body>
</html>
import React from 'react';
import { renderToString } from 'react-dom/server';
import express from 'express';
import path from 'path';
import App from './src/App';
const app = express();
app.set('view engine', 'pug');
app.use('/', express.static(path.join(__dirname, 'dist')));
app.get('*', (req, res) => {
const html = renderToString(
<App />
);
res.render(path.join(__dirname, 'src/index.pug'), {
app: html
});
});
app.listen(3000, () => console.log('listening on port 3000'));
import { renderToString } from 'react-dom/server';
const app = express();
app.set('view engine', 'pug');
app.use('/', express.static(path.join(__dirname, 'dist')));
app.get('*', (req, res) => {});
const html = renderToString(
<App />
);
res.render(path.join(__dirname, 'src/index.pug'), {
app: html
});
app.listen(3000, () => console.log('listening on port 3000'));
"scripts": {
"server": "babel-node server.js"
}
<!doctype html>
<html>
<head>
<meta charset="utf-8" />
</head>
<body>
<div id="root">div data-reactroot="">
Contents of App.js
</div>
<script src="bundle.js"></script>
</body>
</html>

Things to have in mind

  • React component lifecycles are not not called on the server (componentDidMount) it means that fetched data that you are rendering on runtime, won’t be SSR; this is generally a good thing, as you should be providing the data as props if you need it. Remember that you need to delay your render (calling res.render) until the data is fetched, which might introduce some delay for your visitors
  • any state generated on the server side will not be passed to the client application state; that means that if your backend fetches some data and uses it to render HTML, it will not be placed in the this.state that the browser sees
  • if you’re using a react-router you need to make sure that the proper URL is passed to the application when it’s rendered on the server.

--

--

--

Love podcasts or audiobooks? Learn on the go with our new app.

Recommended from Medium

Our React Native App Looks Much Better Now

[React] Event Capturing and Event Bubbling

React Concepts

JavaScript: Check if String contains Substring

Latest on how to integrate paystack using only html and javascript.

A-Z of building dApps on ICE — Part 5: Using Polkadot.js to build dApps.

How to use Redux with AsyncStorage

An Alternative to NPM Link

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store
Mindaugas Nakrosis

Mindaugas Nakrosis

More from Medium

Lazy loading feature of Code Splitting technique in React

Lazy Loading through Code Splitting

Data fetching in React

Profiling — React Applications

An investigative guide to React JS[DOM, Virtual DOM and JSX] Part-VII