

How to Enable Server-Side Rendering for a React App
source link: https://www.digitalocean.com/community/tutorials/react-server-side-rendering
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

Tutorial
How to Enable Server-Side Rendering for a React App
-
By Alligator.io
Last Validated onJanuary 12, 2021 Originally Published onMay 27, 2018 451.5k views
Introduction
Server-side rendering (SSR) is a popular technique for rendering a client-side single page application (SPA) on the server and then sending a fully rendered page to the client. This allows for dynamic components to be served as static HTML markup.
This approach can be useful for search engine optimization (SEO) when indexing does not handle JavaScript properly. It may also be beneficial in situations where downloading a large JavaScript bundle is impaired by a slow network.
In this tutorial, you will initialize a React app using Create React App and then modify the project to enable server-side rendering.
Warning: The code provided in this tutorial is for educational purposes and is not intended for production use. Alternatively, Next.js offers a modern approach to creating static and server-rendered applications built with React.
At the end of this tutorial, you will have a working project with a client-side React application and a server-side Express application.
Prerequisites
To complete this tutorial, you will need:
- Node.js installed locally, which you can do by following How to Install Node.js and Create a Local Development Environment.
This tutorial was verified with Node v14.4.0, npm
v6.14.5, react
v16.13.1, @babel/core
v7.10.4, webpack
v4.42.0, express
v4.17.1, nodemon
v2.0.4, and npm-run-all
v4.1.5.
Step 1 — Creating the React App and Modifying the App Component
First, we use npx to start up a new React app using the latest version of Create React App.
Let’s call our app my-ssr-app:
npx [email protected] my-ssr-app
Then, we cd
into the new directory:
cd my-ssr-app
Finally, we start our new client-side app in order to verify the installation:
npm start
You should see an example React app display in your browser window.
Now, let’s create a <Home>
component:
nano src/Home.js
Next, add the following code to the Home.js
file:
import React from 'react';
export default props => {
return <h1>Hello {props.name}!</h1>;
};
This will create a <h1>
heading with a "Hello"
message directed to a name.
Next, let’s render the <Home>
in the <App>
component. Open the App.js
file:
nano src/App.js
Then, replace the existing lines of code with these new lines of code:
import React from 'react';
import Home from './Home';
export default () => {
return <Home name="Sammy" />;
};
This passes along a name
to <Home>
component so the message that we expect to display is "Hello Sammy!"
.
In our app’s index.js
file, we’ll use ReactDOM’s hydrate
method instead of render
to indicate to the DOM renderer that we’re rehydrating the app after a server-side render.
Let’s open the index.js
file:
nano index.js
Then, replace the contents of the index.js
file with the following code:
import React from 'react';
import ReactDOM from 'react-dom';
import App from './App';
ReactDOM.hydrate(<App />, document.getElementById('root'));
That concludes setting up the client-side, we can move on to setting up the server-side.
Step 2 — Creating an Express Server and Rendering the App Component
Now that we have our app in place, let’s set up a server that will send along a rendered version. We’ll use Express for our server. Let’s add it to the project by entering the following command in your terminal window:
npm install [email protected]
Or, using yarn:
yarn add [email protected]
Next, create a server
directory next to the app’s src
directory:
mkdir server
Then, create a new index.js
file that will contain the Express server code:
nano server/index.js
Add the imports that will need and define some constants:
import path from 'path';
import fs from 'fs';
import React from 'react';
import express from 'express';
import ReactDOMServer from 'react-dom/server';
import App from '../src/App';
const PORT = process.env.PORT || 3006;
const app = express();
Next, add the server code with some error handling:
// ...
app.get('/', (req, res) => {
const app = ReactDOMServer.renderToString(<App />);
const indexFile = path.resolve('./build/index.html');
fs.readFile(indexFile, 'utf8', (err, data) => {
if (err) {
console.error('Something went wrong:', err);
return res.status(500).send('Oops, better luck next time!');
}
return res.send(
data.replace('<div id="root"></div>', `<div id="root">${app}</div>`)
);
});
});
app.use(express.static('./build'));
app.listen(PORT, () => {
console.log(`Server is listening on port ${PORT}`);
});
As you may see, we can import our <App>
component from the client app directly from the server.
Three important things are taking place here:
- We tell Express to serve contents from the
build
directory as static files. - We use a method from
ReactDOMServer
,renderToString
, to render our app to a static HTML string. - We then read the static
index.html
file from the built client app, inject our app’s static content in the<div>
with anid
of"root"
, and send that as the response to the request.
Step 3 — Configuring webpack, Babel, and npm
Scripts
For our server code to work, we’ll need to bundle and transpile it, using webpack and Babel. To accomplish this, let’s add the dev dependencies to the project by entering the following command in your terminal window:
npm install [email protected] [email protected] [email protected] @babel/[email protected] [email protected] @babel/[email protected] @babel/[email protected] --save-dev
Or, using yarn:
yarn add [email protected] [email protected] [email protected] @babel/[email protected] [email protected] @babel/[email protected] @babel/[email protected] --dev
Note: An earlier version of this tutorial installed babel-core
, babel-preset-env
, and babel-preset-react-app
. These packages have since been archived, and the mono repo versions are utilized instead.
Next, create a Babel configuration file in your project’s root directory:
nano .babelrc.json
Then, add the env
and react-app
presets:
{
"presets": [
"@babel/preset-env",
"@babel/preset-react"
]
}
Note: An earlier version of this tutorial used a .babelrc
file (no .json
file extension). This was a configuration file for Babel 6, but this is no longer the case for Babel 7.
Now, we will create a webpack config for the server that uses Babel Loader to transpile the code. Start by creating the webpack.server.js
file in your project root directory:
nano webpack.server.js
Then, add the following configurations to the webpack.server.js
file:
const path = require('path');
const nodeExternals = require('webpack-node-externals');
module.exports = {
entry: './server/index.js',
target: 'node',
externals: [nodeExternals()],
output: {
path: path.resolve('server-build'),
filename: 'index.js'
},
module: {
rules: [
{
test: /\.js$/,
use: 'babel-loader'
}
]
}
};
With this configuration, our transpiled server bundle will be output to the server-build
folder in a file called index.js
.
Note the use of target: 'node'
and externals: [nodeExternals()]
from webpack-node-externals
, which will omit the files from node_modules
in the bundle; the server can access these files directly.
This completes the dependency installation and webpack and Babel configuration.
Now, we will revisit package.json
to add helper npm
scripts:
nano package.json
We will add dev:build-server
, dev:start
, and dev
scripts to the package.json
file to build and serve our SSR application easily:
"scripts": {
"dev:build-server": "NODE_ENV=development webpack --config webpack.server.js --mode=development -w",
"dev:start": "nodemon ./server-build/index.js",
"dev": "npm-run-all --parallel build dev:*",
// ...
},
The dev:build-server
script sets the environment to "development"
and invokes webpack
with the configuration file we created earlier. The dev:start
script invokes nodemon
to serve the built output.
The dev
script invokes npm-run-all
to run in parallel
the build
script and all scripts that start with dev:*
- including dev:build-server
and dev:start
.
Note: You will not need to modify the existing "start"
, "build"
, "test"
, and "eject"
scripts in the package.json
file.
We use nodemon
to restart the server when we make changes to it. And we use npm-run-all
to run multiple commands in parallel.
Let’s install those packages now by entering the following commands in your terminal window:
npm install [email protected] [email protected] --save-dev
Or, using yarn:
yarn add [email protected] [email protected] --dev
With this in place, you can run the following to build the client-side app, bundle and transpile the server code, and start up the server on :3006
:
npm run dev
Or, using yarn:
yarn run dev
Our server webpack config will watch for changes and our server will restart on changes. For the client app, however, we currently still need to build it each time we make changes. There’s an open issue for that here.
Now, open http://localhost:3006/
in your web browser and you will see your server-side rendered app.
Previously, the source code revealed:
Output
<div id="root"></div>
But now, with the changes you made, the source code reveals:
Output
<div id="root"><h1 data-reactroot="">Hello <!-- -->Sammy<!-- -->!</h1></div>
The server-side rendering successfully converted the <App>
component into HTML.
Conclusion
In this tutorial, you initialized a React application and enabled server-side rendering.
With this post, we just scratched the surface at what’s possible. Things tend to get a bit more complicated once routing, data fetching, or Redux also need to be part of a server-side rendered app.
One major benefit of using SSR is having an app that can be crawled for its content, even for crawlers that don’t execute JavaScript code. This can help with search engine optimization (SEO) and providing metadata to social media channels.
SSR can also often help with performance because a fully loaded app is sent down from the server on the first request. For non-trivial apps, your mileage may vary because SSR requires a setup that can get a bit complicated, and it creates a bigger load on the server. Whether to use server-side rendering for your React app depends on your specific needs and on which trade-offs make the most sense for your use case.
If you’d like to learn more about React, take a look at our How To Code in React.js series, or check out our React topic page for exercises and programming projects.
Recommend
-
31
Understanding Server-Side Rendering In this article, we’re going to learn about Server-Side Rendering, what this technique is and why we should consider it when we’re creating new apps. We’re going to learn how...
-
8
In Web Development, one of the core decisions developers have to make is to decide where to implement rendering in their application. The two most common rendering techniques are Client-Side Rendering: renders web page on the brow...
-
9
React Server-side Rendering with ReactJS.NETStep by step guide for React server-side rendering using the ReactJS.NET library
-
4
Oct 21st, 2019Hasty Treat - React Server Side Rendering👇 Download Show✏️ Edit Show Notes
-
5
Using React Suspense for Better Server-Side RenderingImprove user experience and performance in server-side rendering with React suspenseServer-side rendering is increasingly becoming popular among web...
-
10
Inertia - Server-side Rendering (SSR) 以 React 為範例 本文為官方文件翻譯,如使用其他前端框架可參考官方 SSR 支援提前渲染造訪的頁面,並且回傳渲...
-
5
Client-Side Rendering In a standard React application, the browser receives an empty HTML from the server along with the JavaScript instructions to construct the UI. This is called Client-Side Rendering (CSR) beca...
-
9
Unleash the Power of Server-Side Rendering with React Server Components and Next.js 13An overview of the final implementation of this feature
-
11
What’s New in Server Side Rendering: React vs Angular vs Vue.jsExplore the newest releases on server side rendering in React, Angular and Vue.js
-
7
In this post, we'll explain what server-side rendering (SSR) is and how it's different from the usual way websites work. We will run you through how to use SSR with Next.js, React, and TypeScript step-by-step. By the end, you'll know how SS...
About Joyk
Aggregate valuable and interesting links.
Joyk means Joy of geeK