服务端渲染能解决首屏加载过慢的问题,近年来这是一个趋势,这里写一个react的demo,以免忘了。

本文涉及的 react api如下:

  • ReactDOM.hydrate(<App />,document.getElementById('root')
  • ReactDOMServer.renderToString(<App/>)

用脚手架初始化项目

这部分不解释,用脚手架快速生成一个app

!注意: create-react-app 新版本生成的 App.js 已经没有 import React from 'react',我们必须把它加回来,否则服务端渲染会报错:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
+ import React from 'react'
import { useState } from 'react';
import './App.css';

function App() {
const [count, setCount] = useState(0)
return <div className="App">
<p>{count}</p>
<button onClick={()=> setCount(count + 1 )}>+</button>
<button onClick={()=> setCount(count-1)}>-</button>
</div>

}

export default App;

添加服务端

1
2
3
4
yarn add express
# 首页须进行打包操作给服务端做渲染:
yarn build
mkdir server && cd server && touch server.js

server\server.js

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
import express from 'express'
import fs from 'fs'
import path from 'path'

import React from 'react'
import ReactDOMServer from 'react-dom/server'

import App from '../src/App'

const app = express()

app.use('^/$', (req, res, next) =>{
fs.readFile(path.resolve('../build/index.html'), 'utf-8', (err, data) => {
if (err) {
console.log(err)
return res.status(500).send('smoe error happened')
}
return res.send(data.replace(
'<div id="root"></div>',
`<div id="root">${ReactDOMServer.renderToString(<App/>)}</div>`
))
}
)
})

app.use(express.static(path.resolve(__dirname, '..', 'build')))

const PORT = 8888
app.listen(PORT, ()=>console.log(`listen on PORT ${PORT}`))

express 跑起来

src\index.js 改造

1
2
- ReactDOM.render(<App />,document.getElementById('root'))
+ ReactDOM.hydrate(<App />,document.getElementById('root')

添加 babel 让node认识jsx语法

1
yarn add @babel/preset-env @babel/preset-react @babel/register ignore-styles

server 文件夹添加运行 babel 机制

执行touch server/index.js

node原生的必须用 require 的写法导入模块,如下:

1
2
3
4
5
6
7
8
require('ignore-styles')

require('@babel/register')({
ignore: [/(node_module)/],
presets: ['@babel/preset-env', '@babel/preset-react']
})

require('./server')

添加 package.json 里的脚本后再运行 yarn ssr

1
"ssr": "node server/index.js"

我们会发现顺利解析了 jsx 语法:

1
2
3
4
5
yuyi@home-pc MINGW64 /e/study/code/react-ssr-demo (main)
$ yarn ssr
yarn run v1.22.10
$ node server/index.js
listen on PORT 8888

浏览器访问本地8888端口,打开调试工具就会发现已经成功