React typescript server-side rendering in 5 steps

Neeraj Dana
Neeraj Dana

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.

For Software development you can coordinate with my friend John he is a freelance front end developer

Step 1 :Create React App with typescript


npx create-react-app reactssr --template typescript -d


npm install @babel/preset-env @babel/preset-react @babel/preset-stage-0 @babel/preset-typescript
express nodemon npm-run-all webpack-dev-server webpack-merge webpack-node-external

npm i -D @types/express @types/react @types/react-dom @types/node sass-loader ts-loader typescript webpack webpack-cli nodemon npm-run-all webpack-node-externals babel-loader @babel/polyfill css-loader node-sass style-loader

The above command will create a react app with typescript with tsconfig already set for you

Step 2 : Change Render to hydrate

the next step we will update the index.ts file and change the render function to hydrate


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





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

Step 3 : Create a server

Next let's create our server responsible for Server side rendring create a server.ts file with this content

import express from "express";
import React from "react";
import {renderToString} from "react-dom/server";

import App from './src/App'
const app = express();
const port = 3000;
app.use(express.static("public"));

const generateHtml = () => {
  const content = renderToString(React.createElement(App));
  console.log('content',content);
  
  return `
  <html>
  <head>
  
  </head>
  <body>
  
  <div id="root">${content}</div>
  <script src="bundel.js"></script>
  </body>


  </html>
  `;
};

app.get("/", (req, res) => {
res.send(generateHtml());
});
app.listen(port, () => {
  return console.log(`server is  listening on ${port}`);
});

Step 4 : integrate webpack

next we will create a webpack.config.js file o bunle our app and use es6+ in our code


const path = require("path");
const webpackNodeExternals = require("webpack-node-externals");

module.exports = {
    //inform creating a bundel for node js
   
    resolve: {
      extensions: [".tsx", ".ts", ".js",'.scss','.css'],
    },
    target: "node",
    entry: ["@babel/polyfill", "./server.ts"],
    output: {
      filename: "bundel.js",
      path: path.resolve(__dirname, "build"),
    },
    externals: [webpackNodeExternals()],
    module: {
      rules: [
        {
          test: /\.s[ac]ss$/i,
          use: [
            // Creates `style` nodes from JS strings
            "style-loader",
            // Translates CSS into CommonJS
            "css-loader",
            // Compiles Sass to CSS
            "sass-loader"
            
          ],
        },
        {
          test: /\.css$/i,
          
          use: ['style-loader', 'css-loader'],
        },
        {
          test: /\.(js|(j|t)sx?)$/,
          loader: "babel-loader",
          exclude: /node_modules/,
          options: {
            presets: [
              "@babel/react",
              "@babel/preset-typescript",
              [
                "@babel/env",
                {
                  targets: {
                    browsers: ["last 2 versions"],
                  },
                },
              ],
            ],
          },
        },
      ],
    },
  };
  

Step 5 : Test the app

next update the package.json and insert following scripts

"dev:server": "nodemon --watch build --exec \"node build/bundel.js\"",
"dev:build:server": "webpack --config webpack.server.js --watch",
 "dev": "run-p dev:build:server dev:build:client dev:server*",

The dev:build:server is for building the app it will create a build folder and convert our code so that it can be run through node

The dev:server is for running the app from build folder

npm run dev

this command should start and run both the commands in parallel and if everyting gows well we will be also to see our ssr app on port 3000

In the next article we will see how we can use react router and redux in react typescripr server side rendered app.