最近看了下 React SSR
相关的东西,这里记录一下相关内容
本文实例代码已经上传到 github,感兴趣的可参见 Basic | SplitChunkV
初识 React SSR
nodejs
遵循 commonjs
规范,文件的导入导出如下:
// 导出
module.exports = someModule
// 导入
const module = require('./someModule')
而我们通常所写的 react
代码是遵循 esModule
规范的,文件的导入导出如下:
// 导出
export default someModule
// 导入
import module from './someModule'
所以想要让 react
代码兼容于服务器端,就必须先解决这两种规范的兼容问题,实际上 react
是可以直接以 commonjs
规范来书写的,例如:
const React = require('react')
这样一看似乎就是个写法的转换罢了,没什么问题,但实际上,这只是解决了其中一个问题而已,react
中常见的渲染代码,即 jsx
,node
是不认识的,必须要编译一次
render () {
// node是不认识 jsx的
return <div>home</div>
}
客户端编译 react
代码用到最多的就是 webpack
,服务器端同样可以使用,这里使用 webpack
的作用有两个:
- 将
jsx
编译为node
认识的原生js
代码 - 将
exModule
代码编译成commonjs
的
webpack
示例配置文件如下:
// webpack.server.js
module.exports = {
// 省略代码...
module: {
rules: [
{
test: /\.js$/,
loader: 'babel-loader',
exclude: /node_modules/,
options: {
// 需要支持 react
// 需要转换 stage-0
presets: ['react', 'stage-0', ['env', {
targets: {
browsers: ['last 2 versions']
}
}]]
}
}
]
}
}
有了这份配置文件之后,就可以愉快的写代码了
首先是一份需要输出到客户端的 react
代码:
import React from 'react'
export default () => {
return <div>home</div>
}
这份代码很简单,就是一个普通的 react stateless
组件
然后是负责将这个组件输出到客户端的服务器端代码:
// index.js
import http from 'http'
import React from 'react'
import {
renderToString } from 'react-dom/server'
import Home from './containers/Home/index.js'
const container = renderToString(<Home />)
http.createServer((request, response) => {
response.writeHead(200, {
'Content-Type': 'text/html'})
response.end(`
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
</head>
<body>
<div id="root">${
container}</div>
</body>
</html>
`)
}).listen(8888)
console.log('Server running at http://127.0.0.1:8888/')
上述代码就是启动了一个 node http
服务器,响应了一个 html
页面源码,只不过相比于常见的 node
服务器端代码而言,这里还引入了 react
相关库
我们通常所写的 React
代码,其渲染页面的动作,其实是 react
调用浏览器相关 API
实时进行的,即页面是由 js
操纵浏览器DOM API
组装而成,服务器端是无法调用浏览器 API
的,所以这个过程无法进行,这个时候就需要借助 renderToString
了
renderToString
是 React
提供的用于将 React
代码转换为浏览器可直接识别的 html
字符串的 API
,可以认为此 API
提前将浏览器要做的事情做好了,直接在服务器端将DOM
字符串拼凑完成,交给 node
输出到浏览器
上述代码中的变量 container
,其实就是如下的 html
字符串:
<div data-reactroot="">home</div