实现 react 服务器渲染的通常思路是使用 node 服务器即时渲染组件并生成页面数据流返回给浏览器,最简单版本的 node 服务器渲染:https://github.com/codelegant/react-server-simple
但是这种实现方式有以下缺点:
如果原来有 node 服务器还好,否则需要额外架设服务器
对前端开发者并不是特别友好
即时渲染组件,比较耗费资源
那有没有不需要架设 node 服务器,实现方式又很前端,并且可以预渲染并生成静态文件的方式呢?答案是:有的!只需要用到两个工具:webpack 与 html-webpack-plugin。
首先,我们知道,webpack 是工作在 node 环境下的,这意味着我们可以在其中调用ReactDOMServer,服务器渲染的功能实现了。其次,html-webpack-plugin 用于生成 html 文件,并且我们可以使用自己模板并插值,这样就允许我们将上一步生成的组件插入到模板中,并生成 html 文件,这样就实现了真静态。
新建一个名为 ItemList 的组件,注意模块的导入导出写法:
/**
* public/src/server-render/ItemList.js
* node 不支持 ES6 的 export 与 import关键字,所以需要使用 module.exports 导出模块
* 但是当导出模块之后,可以使用 babel-register 转换,所以可以在模块内部使用 import。
*/
import React,{PropTypes} from 'react';
module.exports = class ItemList extends React.Component {
static propTypes={
items:PropTypes.arrayOf(PropTypes.string)
};
constructor(props) {
super(props);
this.state = {
items:props.items
};
this.handleClick = this.handleClick.bind(this);
}
handleClick() {
return this.setState({
items:this.state.items.concat(`Item ${this.state.items.length+1}`)
});
}
render() {
return (
Add Item
{this.state.items.map((item,index)=>
{item})});
}
};
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
30
31
32
33
34
35
/**
* public/src/server-render/ItemList.js
* node 不支持 ES6 的 export 与 import关键字,所以需要使用 module.exports 导出模块
* 但是当导出模块之后,可以使用 babel-register 转换,所以可以在模块内部使用 import。
*/
importReact,{PropTypes}from'react';
module.exports=classItemListextendsReact.Component{
staticpropTypes={
items:PropTypes.arrayOf(PropTypes.string)
};
constructor(props){
super(props);
this.state={
items:props.items
};
this.handleClick=this.handleClick.bind(this);
}
handleClick(){
returnthis.setState({
items:this.state.items.concat(`Item${this.state.items.length+1}`)
});
}
render(){
return(
AddItem
{this.state.items.map((item,index)=>{item})}
);
}
};
然后添加静态数据与服务器渲染代码:
//public/src/server-render/model.js
module.exports = {
items: [
'Item 1',
'Item 2',
'Item 3'
]
};
//public/src/server-render/browser.js
import React from 'react';
import {render} from 'react-dom';
const ItemList=require('./ItemList');
const model=require('./model');
render(, document.getElementById('container'));
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
//public/src/server-render/model.js
module.exports={
items:[
'Item 1',
'Item 2',
'Item 3'
]
};
//public/src/server-render/browser.js
importReactfrom'react';
import{render}from'react-dom';
constItemList=require('./ItemList');
constmodel=require('./model');
render(,document.getElementById('container'));
添加 html 模板文件:
content="" />
content="" />
content="width=1200" />
content="webkit" />
content="IE=edge" />
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
content=""/>
content=""/>
content="width=1200"/>
content="webkit"/>
content="IE=edge"/>