The React SSR profile

Client Rendering (CSR) : The server only returns JSON DATA, and DATA and HTML are rendered on the client side.

Server side Rendering (SSR) : The server side returns HTML, and DATA and HTML are rendered on the server side.

Problems with client rendering:

1. Long waiting time for the first screen and poor user experience.

Client-side rendering process: The first time a server responds to a request from the client, it returns an empty HTML document, called index.html, which contains only the outer chains of CSS and JS. The browser starts executing the Html document and then requests CSS and JS externals from the server. After obtaining the JS file, it requests the server for the data of the page. Wait for the data to come back, and then wait for JS to put the data together, and then at this time the client interface will be blank to appear content.

Server-side rendering process: The server first returns the HTML and data stitched together, and the user can see the content of the page, albeit a static page. Then the JS request is sent, the CONTENT of the JS is parsed, and finally the page has a dynamic effect. And return is a complete HTML page, conducive to the implementation of the search engine.

2. Empty page structure is not conducive to SEO.

The core of React SSR lies in isomorphism, which enables code reuse and maximizes code reuse between client and server.

Preliminary rendering

Render the React component into an HTML string using renderToString. 3. Send the resulting HTML string to the client

Webpack configuration: Node environment does not support ESModule system, does not support JSX syntax.

Add events to the element

It starts by returning only the HTML structure, without any JS code, and makes a second rendering on the client side to add events to the component elements. Hydrate can be re-rendered on the client side, reuse existing and Dom nodes, reduce the overhead of regenerating nodes and deleting original nodes, and import hydrate via react-DOM.

Do a secondary render on the client side using Hydrate.

ReactDom.hydrate(<Home/>.document.getElementById("root"))
Copy the code

2. Add Babel configuration.

const path = require('path')
module.exports = {
    mode:"development".entry:"./src/client/index.js".output: {path:path.join(__dirname,"public"),
        filename:"bundle.js"
    },
    module: {rules:[
            {
                test:/\.js$/,
                exclude:/node_modules/,
                use:{
                    loader:"babel-loader".options: {presets: ["@babel/preset-env"."@babel/preset-react"}}}]}}Copy the code

3. In the Html structure returned by the server, add

<html>
            <head>
                <title> React ssr </title>
            </head>
            <body>
                <div id ="root"> ${content} </div>
                <script src = "bundle.js">  </script>
            </body>
        </html>
Copy the code

4, the server to achieve static resource access.

app.use(express.static("public"));
Copy the code

Some optimizations: 1, merge the webpack:webpack-merge 2, merge the project startup command :npm-run-all 3, server side large package volume optimization: webpack-node-externals 4, will start the server code and render component code to distinguish

Routing implementation

Server-side routing implementation:

1. Set unified routing rules and export the routing form of array objects. 2. Use renderRoute to convert array objects to component form. 3. Use StaticRouter to match routes

Part of the code

import { renderToString }  from 'react-dom/server'
import { renderRoutes }  from "react-router-config"
import { StaticRouter } from "react-router-dom"
import routes from '.. /share/routes'


export default req => {
    const content = renderToString(<StaticRouter location= {req.path}> {renderRoutes(routes)}</StaticRouter>)
    return `
    <html>
        <head>
            <title> React ssr </title>
        </head>
        <body>
            <div id ="root"> ${content} </div>
            <script src = "bundle.js">  </script>
        </body>
    </html>

`
}

Copy the code

Client routing implementation:

import React from "react"

import ReactDom from "react-dom"

import { BrowserRouter } from "react-router-dom"

import { renderRoutes } from 'react-router-config'

import routes from '.. /share/routes'

ReactDom.hydrate(<BrowserRouter>{renderRoutes(routes)}</BrowserRouter>.document.getElementById("root"))
Copy the code