In the first two articles, I wrote “Implement your own React server render manually” and “Isomorphic Render under React”.
Today I will combine these two articles to talk about how to optimize isomorphic rendering under React.
Start with the following four points.
– Configuration file optimization
– Start instruction optimization
– Package volume optimization
– Code split
# config file merge
Both the client and the server have their own configuration files.
Webpack.client. js and webpack.config.js have a lot in common at the content level.
So we need to extract the same code, create a single base file, webpack.common.js, and then assemble it with a dependency package called webpack-merge.
– npm install webpack-merge
Webpack.common.js same code extracted:
//webpack.common.js content const path = require("path") module.exports = {mode:"development", module:{ rules:[ { test:/\.js$/, exclude:/node_modules/, use:{ loader:"babel-loader", options:{ presets:["@babel/preset-env","@babel/preset-react"] } } } ] } }Copy the code
Webpack.client. js Client package file contents:
//webpack.client.js
const path = require("path")
const {merge} = require("webpack-merge")
const baseConfig = require("./webpack.common")
const config= {
entry:"./src/client/index.js",
output:{
path:path.join(__dirname,"public"),
filename:"build.js"
}
}
module.exports = merge(baseConfig,config)
Copy the code
Webpack.server. js Server side package file contents:
//webpack.server.js
const path = require("path")
const {merge} = require("webpack-merge")
const baseConfig = require("./webpack.common")
const config = {
target:"node",
entry:"./src/server/index.js",
output:{
path:path.join(__dirname,"build"),
filename:"bundle.js"
}
}
module.exports = merge(baseConfig,config)
Copy the code
This completes the basic configuration file merge.
Start instruction optimization
Under the scripts of package.json, we configure many directives: client packaging directives, server packaging directives, server startup directives.
Now one thing we need to do is run all three of these instructions in one instruction.
Here we use a tool called npm-run-all.
– Npm install npm-run-all
//package.json
"scripts": {
"dev": "npm-run-all --parallel dev:*",
"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 build --exec \"node build/bundle.js\""
},
Copy the code
For writing these instructions, look up the corresponding API in the address.
After configuration, we only need a single command NPM run dev to do all three commands.
# Exclude built-in module packaging
After being packaged on the server side, you can see that the package file is extremely large, reaching several megabytes.
This is because it packs some node built-in modules in the packaging process, so we need to filter these node built-in modules in the packaging process.
Here we need the tool webpack-node-externals.
– Npm install webpack-node-externals
In webpack.server.js, we add a property.
//webpack.server.js const path = require("path") const {merge} = require("webpack-merge") const nodeExternals = require("webpack-node-externals") const baseConfig = require("./webpack.common") const config = { target:"node", entry:"./src/server/index.js", output:{ path:path.join(__dirname,"build"), filename:"bundle.js" }, Externals :[nodeExternals()] // new added} module.exports = merge(baseConfig,config)Copy the code
And then when you pack it up again, you can see that there are a lot fewer files packed under server.
# Code split
You are advised to separate each function module during service writing to facilitate project maintenance and iterative development.
So in index.js in the server directory, routing and rendering need to be separated and not mixed together.
So we need to create a separate render. Js file that looks like this:
//server/render.js import React from "react" import Home from ".. /common/pages/home"; import { renderToString } from "react-dom/server" export default ()=>{ const content = renderToString(<Home/>) return ` <html> <head> </head> <body> <div id="root">${content}</div> </body> <script src="build.js"></script> </html> ` }Copy the code
Contents under server/index.js:
//server/index.js
import app from "./http"
import render from "./render"
app.get("/",(req,res)=>{
res.send(render())
})
Copy the code
These are some of the optimizations I have listed under React isomorphic rendering. I hope you will find them helpful during the development process