создать реагирующее приложение

npx create-react-app reactssr

когда эта команда завершится, перейдите в каталог проекта и следуйте

Шаг 2: Используйте гидрат React

Это то же самое, что и render(), но используется для гидратации контейнера, HTML-содержимое которого было обработано ReactDOMServer. React попытается прикрепить прослушиватели событий к существующей разметке.

React ожидает, что отображаемый контент идентичен между сервером и клиентом. Он может исправлять различия в текстовом содержании, но вы должны рассматривать несоответствия как ошибки и исправлять их. В режиме разработки React предупреждает о несоответствиях во время гидратации. Нет никаких гарантий, что различия атрибутов будут исправлены в случае несоответствия. Это важно с точки зрения производительности, поскольку в большинстве приложений несоответствия случаются редко, и поэтому проверка всей разметки будет непомерно дорогой.

перейдите в папку src и файл index.js и измените

ReactDOM.render

to

ReactDOM.hydrate

Шаг 3: Установите зависимости

npm install ignore-styles
    @babel/preset-env
    @babel/preset-react
    @babel/register
    ignore-styles -D
npm i express react-helmet --save

Шаг 4: Создайте экспресс-сервер

создайте папку сервера с server.js в маршруте вашего проекта

import App from '../src/App'
const {Helmet} = require('react-helmet');
const path=require('path');

const fs=require('fs');
const express=require('express');
const React=require('react');
const ReactDOMServer=require('react-dom/server');

const PORT = 9000
const app = express()
const router = express.Router()

const GetData = (req, res, next) => {
    const renderData = ReactDOMServer.renderToString(<App />);
  const helmet = Helmet.renderStatic();
  fs.readFile(path.resolve('./build/index.html'), 'utf8', (err, data) => {
    if (err) {
      console.error(err)
      return res.status(500).send('An error occurred')
    }
    return res.send(
      data.replace(
        '<div id="root"></div>',
        `
        <!doctype html>
    <html ${helmet.htmlAttributes.toString()}>
        <head>
            ${helmet.title.toString()}
            ${helmet.meta.toString()}
            ${helmet.link.toString()}
        </head>
        <body ${helmet.bodyAttributes.toString()}>
        <div id="root">${renderData}</div>
        </body>
    </html>
        
       `
      )
    )
  })
}
router.use('^/$', GetData)

router.use(
  express.static(path.resolve(__dirname, '..', 'build'))
)

app.use(router)

app.listen(PORT, () => {
  console.log(`See the magic at ${PORT}`)
})

создать индексный файл в папке сервера

require('ignore-styles')

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

чтобы увидеть некоторые SEO-материалы в действии, измените компонент приложения на

import React from "react";

import "./App.css";


function App() {
  return (
    <>
      <Helmet>
                <meta charSet="utf-8" />
                <title>Learn software development</title>
                <meta 
                name="og:title"
                content="Learn software development from the best"/>

                
                 
            </Helmet>
            <p>See the title of the page</p>
    </>
  );
}

export default App;

Наконец создайте свое приложение с помощью

npm run build

//and  then do 

node server/index.js

перейти на http://localhost:9000

TODO: в продолжении этой статьи мы интегрируем веб-пакет для горячей перезагрузки нашего приложения.