1. 新增环境依赖
React 16 依赖于ES6新增集合类型 Map 和 Set。若执行环境不支持,可以使用core-js进行polyfill。
import 'core-js/es6/map';
import 'core-js/es6/set';
import React from 'react';
import ReactDOM from 'react-dom';
React16 也依赖于 requestAnimationFrame。
2. 新增客户端增量渲染能力
React16对服务端渲染做了很多优化,真正做到了:
服务端首次渲染,客户端增量渲染(目前还非常不好用)并添加事件`
React15只能做到:服务端首次渲染,客户端添加事件;使用React15时服务端渲染与客户端首次渲染的任何不一致,都会导致服务端渲染输出的DOM树被替换。
React16保证:在development模式使用React15没有任何warning时,可以无缝升级到React16。
但我们很难做到服务端渲染输出的DOM和客户端首次渲染输出的DOM完全一致;这就使得升级React16变得困难。针对这种状况,目前主要有三种升级思路:
2.1 简单升级,完全放弃新特性
基于React15时,我们往往误用renderToString,通过renderToString渲染DOM,然后在客户端通过ReactDOM.render渲染出有局部差异
的DOM;然而由于React15对服务端渲染DOM和客户端渲染DOM执行严格的一致性检查,所以会用客户端渲染输出DOM替换服务端渲染输出的DOM;这种情况下使用renderToString并不比renderToStaticMarkup有性能优势。
针对这种情况,升级到React16后,我们可以仍然使用renderToStaticMarkup输出服务端DOM,客户端也会使用ReactDOM.render输出的DOM替换服务端输出的DOM;相比React15没有性能上的降级。
2.3 谨慎升级,客户端不进行增量渲染
放弃服务端渲染会导致用户可交互时间变长,并不是最优选择。在保证服务端渲染输出的DOM和客户端首次渲染输出的DOM完全一致的情况下,我们可以安全地使用React16,在客户端添加DOM事件。
针对客户端首次渲染的差异性要求,可以组件挂载后设置组件的状态来触发组件重新渲染。比如如下代码:
<div className={isInNavigator?"clientClass":"serverClass"}}>
</div>
可改为:
state={
divClass: "serverClass"
}
componentDidMount(){
this.setState({
divClass: "clientClass"
});
}
<div className={this.state.divClass}>
</div>
2.3 谨慎升级,客户端进行增量渲染
React16新增了客户端首次增量渲染的能力,但我们必须非常小心地使用它,因为它并不如我们想象般聪明。目前发现增量渲染有如下问题:
(1). 无法触发标签属性变更
(2). 兄弟DOM结构的删除导致页面混乱
由于React16的客户端首次增量渲染有不少奇怪的问题,目前较为安全的做法是:
保证服务端渲染输出的DOM结构与客户端首次渲染输出的DOM结构完全一致,客户端不做增量渲染,仅添加DOM事件。
https://github.com/reactjs/react-basic/blob/master/README.md