react服务端渲染
服务端渲染
前期准备工作
我们首先新建一个文件夹用于存放所有文件
> mkdir reacr-server-side-rendering
接着我们初始化npm包,初始化完成之后,我们需要安装以下npm包以便我们开发服务端渲染实例。
> npm init
> npm i react,..... --save
- react UI框架
- express 服务端框架
- react-dom react转换成字符串
- react-transmit 提前执行请求,本次项目中未使用
- babel-cli 编译
- babel-loader
- babel-preset-es2015
- babel-preset-react
安装完成之后,由于我们使用的是babel-cli集成的babel-node工具,那么我们需要配置babel的编译选项.
需要设置.babelrc 设置编译react
{
"presets": ["react", "es2015"]
}
编写React组件
由于我们只是做一个Demo展示,所以我们简单的进行文件架构。如果你们应用在实际项目中,请根据自身项目进行配置。
我们首先创建一个首页展示组件,代码如下。
Index.js
import React from 'react';
import ButtonNormal from './ButtonNormal';
export default class Index extends React.Component {
constructor () {
super()
};
componentWillMount () {}
componentDidMount () {}
shouldComponentUpdate () {return true;}
componentWillUpdate () {}
componentDidUpdate () {}
componentWillUnmount () {}
render () {
return (<div>
<h1>这是一个服务端渲染的react组件</h1>
<p>
<ButtonNormal>我是一个按钮</ButtonNormal>
</p>
<p>
<ButtonNormal />
</p>
</div>);
}
}
另外我们做了一点简单的组件引用,我们再次创建一个名为ButtonNormal.js文件。
ButtonNormal.js
import React, {Component} from 'react';
export default class ButtonNormal extends Component {
constructor (props) {
super(props);
this.state={
text:props.children||props.text||'确定'
}
};
componentWillMount () {}
componentDidMount () {}
shouldComponentUpdate () {return true;}
componentWillUpdate () {}
componentDidUpdate () {}
componentWillUnmount () {}
render () {
return (
<button>{this.state.text}</button>
);
}
}
编写服务端渲染代码
我们已经完成了React的组件编写,那么我们现在需要进行服务端渲染的开发了。下面就是服务端代码。
const express = require('express');
const fs = require('fs');
const path = require('path');
const React = require('React');
const ReactDOMServer = require('react-dom/server');
const Index = require('./app/index').default;
const app = express();
// 使用我们的 handleRender 中间件处理服务端请求
app.get('*', (req, res)=> {
// 把 Hello 组件渲染成 HTML 字符串
// console.log(Index);
// const html = ReactDOMServer.renderToStaticMarkup(React.createElement(Index.default));
const html = ReactDOMServer.renderToString(<Index/>);
// 加载 index.html 的内容
fs.readFile(__dirname + '/app/templates/index.html', 'utf8', function (err, data) {
if (err) throw err;
// 把渲染后的 React HTML 插入到 div 中
const document = data.replace(/<div id="app"><\/div>/, `<div id="app">${html}</div>`);
// 把响应传回给客户端
res.send(document);
});
});
// 启动服务器
app.listen(3101);
服务端渲染的原理就是通过ReactDOM读取渲染完成的html字符串,然后将字符串替换进现有的服务端文件模版中,最后输出至客户端进行渲染。
这个操作也就是我们将之前的前端渲染逻辑放置在后端进行处理。由于前端技术日新月异,所以,具体将渲染放置在哪一步由具体的业务决定。
require('./app/index').default
由于我们采用了babel-node运行,require进入的文件是一个object,所以我们直接将默认default的方法进行赋值。
运行项目
配置package.json文件,在scripts中增加开发配置
"dev": "babel-node ./src/server.js"
打开命令行环境,运行npm run dev
项目已上传至 GitHub - yodfz/react-server-side-rendering: react服务端渲染
参考文章
- 译 React 在服务端渲染的实现 - 掘金
- https://cmsdk.com/node-js/reactdomserver-rendertostaticmarkup-on-nodeexpress-server.html