React 下同构渲染的优化手段

170 阅读1分钟

前面两篇文章我写了“手动实现一个自己的 React 服务端渲染”和“React 下的同构渲染”。

今天我会结合这两篇文章来聊聊如何优化 React 下的同构渲染

主要从下面四点着手。

- 配置文件优化

- 启动指令优化

- 打包体积优化

- 代码拆分

# 配置文件合并

不论客户端还是服务端,都存在一套自己的配置文件。

webpack.client.js 和 webpack.config.js 在内容层面,这里面的内容有很多相同之处。

所以我们需要把这些雷同的代码抽取出来,单独创建一个基准文件 webpack.common.js,然后通过一个叫 webpack-merge 的依赖包对它们进行拼装。

- npm install webpack-merge

webpack.common.js 相同代码抽离:

//webpack.common.js 内容
 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"]
                     }
                 }
             }
         ]
     }
 }

webpack.client.js 客户端打包文件内容:

//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)

webpack.server.js 服务端打包文件内容:

//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)

这样,基本的配置文件合并我们就完成了。

# 启动指令优化

在 package.json 的 scripts 下,我们配置了很多指令:客户端打包指令,服务端打包指令,服务器启动指令。

现在我们要做一件事,那就是用一个指令把这三个指令全部都运行了。

在这里我们使用一个工具 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\""
  },

对于这些指令的书写,可以去地址中查找对应的 API。

配置完之后我们只需要一个指令 npm run dev 就可以搞定这三个指令的启动。

# 排除内置模块打包

在服务端打包后,可以看到这个打包文件特别大,达到了好几兆。

这是因为它在打包的过程中把一些 node 的内置模块也一起打包了,所以我们需要把这些 node 内置模块在打包的时候过滤掉。

这里我们需要工具 webpack-node-externals。

- Npm install webpack-node-externals

在 webpack.server.js 中,我们添加一个属性。

//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()]  //新添加的
 }

 ​module.exports = merge(baseConfig,config)

之后再打包之后就可以看到 server 下打包的文件少了很多。

# 代码拆分

在写业务的过程中,建议将各个功能模块独立分开,这样便于项目维护和迭代开发。

所以在 server 目录下的 index.js 中,路由和渲染需要分离,不能混合在一起。

所以我们需要单独建立一个 render.js 文件,内容如下:

//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>
     `
}

在 server/index.js 下的内容:

//server/index.js
import app from "./http"
import render from "./render"
app.get("/",(req,res)=>{
    res.send(render())
})

以上就是 React 同构渲染下我所列出的部分性能优化,希望在开发过程中能对你有所帮助~