Server Side Rendering (SSR) and Client Side Rendering (CSR)
- Server render: On the server side, concatenate the content you want to render directly into AN HTML string and return it to the client for rendering.
- Client-side rendering: After the browser loads and parses the HTML, execute the JS code, which inserts the content you want to render into the page.
Compared with client side rendering, server side rendering has advantages and disadvantages as follows:
(1) Speed up the rendering of the first screen (2) is conducive to SEO optimization, improve the ranking in the search engine.Copy the code
Disadvantages include:
(1) Higher requirements for developers, to understand the knowledge of the server. (2) Increased the cost of development operation and maintenance, server resource overhead is relatively large.Copy the code
Therefore, in our development, what kind of rendering method to use should be determined according to the specific business scenario, and do not use server-side rendering until absolutely necessary.
Basic process of server rendering
- Initialize the NPM package, install Express or KOA (I’m using KOA here), and set up the local server.
Then write the server entry file server/index.js, the code is as follows:
import Koa from "koa"; import fs from "fs"; import path from "path"; import React from "react"; import { renderToString } from "react-dom/server"; import Home from ".. /src/page/home/index.jsx"; const app = new Koa(); const rootPath = process.cwd(); Const templatePath = path.join(rootPath, "public/index.html"); // Const templatePath = path.join(rootPath, "public/index.html"); Const template = fs.readfilesync (templatePath).tostring (); app.use(async (ctx) => { const ssrContent = renderToString(<Home />); // Replace the template HTML content with the component content const HTML = template.replace("<! -- ssr slot -->", ssrContent); // return ctx.body = HTML to the browser; }); app.listen(3000);Copy the code
The Home component code is as follows:
import React from "react"; Const Home = () => {const showInfo = () => alert(' user clicked '); return <div className="home" onClick={showInfo}>Home</div> } export default Home;Copy the code
The template HTML content is as follows:
<! DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta Name ="viewport" content="width=device-width, initial-scale=1.0"> <title>Document</title> </head> <body>! -- ssr slot --> </body> </html>Copy the code
The basic server setup is now complete.
- The server webpack configuration packages the Server react code. Install the following plug-in:
Create the webpack.server.js file in the root directory as follows:
const path = require("path"); const nodeExternal = require("webpack-node-externals"); module.exports = { mode: "development", target: "node", entry: path.resolve(__dirname, "./server/index.js"), output: Resolve (__dirname, "./server-build"), // Output path filename: "server-bundle.js", // packaged file}, externals: [nodeExternal()], module: { rules: [ { test: /\.(js|jsx)$/, loader: "babel-loader", exclude: /node_modules/, }, ], }, };Copy the code
Babel configuration file.
{ "presets": ["@babel/preset-react",// react switch rule "@babel/preset-env" // ES2015 rule], "plugins":[ "@babel/plugin-transform-runtime" ] }Copy the code
The package.json script is as follows:
Now run NPM run build:server and run node./server-build/server-build.js (localhost:3000). However, now we add click events to the component, the browser side will not respond, because the server side is only responsible for the early rendering work, not the user interaction and other operations, these operations are still handed to the browser JS. So now we need to package and compile the client React code and introduce (a process called isomorphism).
- Create client/index.js as follows:
import React from "react"; import ReactDom from "react-dom"; import Home from ".. /src/page/home/index.jsx"; ReactDom.hydrate(<Home />, document.getElementById("root"));Copy the code
- Client Webpack configuration, the client react code package, installed plug-ins and server. Create a new webpack.client.js file in the root directory and configure it as follows:
const path = require("path"); module.exports = { mode: "development", entry: Path.resolve (__dirname, "./client/index.js"), // specify the entry file from which the program is compiled, the current directory of __dirname,.. Resolve (__dirname, "./client-build"), // The output path filename: "Client - bundle. Js", / / file} after packaging, the module: {rules: [{test: / \. (js | JSX) $/, loader: "Babel - loader", exclude: /node_modules/, }, ], }, };Copy the code
The package.json script is as follows:
After the NPM run build: Client package is complete, template HTML imports the client-packaged code and configure static resource access on the server side. The code is as follows:
// Template HTML <! DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8" /> <meta http-equiv="X-UA-Compatible" content="IE=edge" /> <meta name="viewport" content="width=device-width, Initial scale = 1.0 "/ > < title > Document < / title > < / head > < body > + < div id =" root "> <! -- ssr slot --></div> + <script src="/client-bundle.js"></script> </body> </html> / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / the server code import Koa from "Koa"; import fs from "fs"; import KoaStatic from "koa-static"; import path from "path"; import React from "react"; import { renderToString } from "react-dom/server"; import Home from ".. /src/page/home/index.jsx"; const app = new Koa(); const rootPath = process.cwd(); + // Static file path + const staticPath1 = path.join(rootPath, "client-build"); Const templatePath = path.join(rootPath, "public/index.html"); // Const templatePath = path.join(rootPath, "public/index.html"); Const template = fs.readfilesync (templatePath).tostring (); + // Access static files + app.use(KoaStatic(staticPath1)); app.use(async (ctx) => { const ssrContent = renderToString(<Home />); // Replace the template HTML content with the component content const HTML = template.replace("<! -- ssr slot -->", ssrContent); console.log(html); // return ctx.body = HTML to the browser; }); app.listen(3000);Copy the code
At this stage, if the server code or client code is changed, we need to manually execute the command to see the latest results. Next, configure webPack to complete automatic packaging. First, install nodemon and npm-run-all plug-ins, and then configure the script command of package.json. The code is as follows:
Now we just need to run NPM run dev and refresh the browser to get the latest results when our files are updated.
React-router-dom and Redux will be added gradually. Pay attention to github repository address