Yesterday posted how to manually implement a Reac SSR for your own server rendering. The React client rendering of CSR is familiar to all of us, so I’ll give you a brief introduction.
# WebPack configuration under Client
Create a webpack.client.js file in the directory of the current project, which is the client packaged processing file with the following contents:
//webpack.client.js
const path = require("path")
module.exports = {
mode:"none",
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
The content of the webpack.client.js configuration file is different from that of the webpack.server.js file in terms of entry attribute values.
The entry file of webpack.client.js is the index.js file under the client. This index.js file is also often written by us, but it should be noted that the writing content of it has been changed.
//client/index.js import React from "react" import ReactDOM from "react-dom" import Home from ".. /common/pages/home" ReactDOM.hydrate(<Home/>,document.getElementById("root"))Copy the code
Instead of using reactdom.render (), we have reactdom.hydrate () instead.
Learn more about Hydrate here.
It is a secondary rendering of the server rendered result, which is a purely static page.
JavaScript code related to some user action requires a secondary rendering of Hydrate, which loads the JavaScript code for execution.
Another thing that’s different is where you pack it and store it.
To summarize the processing results of both:
-
For server rendering, we package the index.js file corresponding to the server into the dist directory. The generated file is called build.js
-
For client rendering, we package the corresponding index.js file under client into the public directory. The generated file is called bundle.js
# config directive
Once the configuration file is written, we need to configure the client packaging instructions. Open the package.json file and configure the client packaging directive in scripts:
//package.json"
scripts": {
"dev:server-build": "npx webpack --config webpack.server.js --watch",
"dev:client-build": "npx webpack --config webpack.client.js --watch"
"dev:server-run": "nodemon --watch dist --exec \"node dist/build.js\""
},
Copy the code
Here we can see that we have added the –watch parameter (see wenpack configuration for this feature). After configuration packaging, we have also configured Nodemon to monitor the dist directory and execute dist/build.js.
# Turning point
Now that we have both client and server packaging configured, we need to think:
How does the client execute the public/bundle.js file during the secondary rendering?
We need to solve it in two steps:
1. We need to add script tags to the file index.js under the server to introduce the bundle.js packaged by the client
//server/index.js
import app from "./http"
import React from "react"
import Home from "../common/pages/home";
import { renderToString } from "react-dom/server"
app.get("/",(req,res)=>{
const content = renderToString(<Home/>)
res.send(`
<html>
<head>
</head>
<body>
<div id="root">${content}</div>
</body>
<script src="build.js"></script>
</html>
`)
})
Copy the code
2. Configure static files
Configure static resource files in server/http.js
//server/http.js
// import express from "express"
const express = require("express")
const app = express()
app.use(express.static("public"))
app.listen(3000,() => {
console.log("sdfdsfsf")
})
export default app;
Copy the code
At this point, a complete server-side rendering and client-side rendering of the small project has been set up. For both rendering, we call it isomorphic rendering.
Next, let’s talk about common optimization methods for isomorphic rendering.