β

React 16

黯羽轻扬 4 阅读

一.特性

fragment

模版支持 fragment string 类型,对应ReactElement数组和字符串

v16.2.0还提供了 JSX的fragment支持 <></>

error boundary

组件级 错误处理 ,支持捕获子组件树内部异常,UI层的兜底方案

portal

允许组件树与DOM树结构不一致,用于hovercards,tooltips等场景

例如tooltip在DOM结构上target与tip一般是兄弟关系(布局需要),而逻辑上tip是属于target的,是父子关系,portals特性用来处理这种场景

特殊的,事件冒泡经过处理,portals组件的父组件仍然能接到冒泡通知(React 16之前就内置了用来抹平DOM事件冒泡差异的事件系统,这里顺便支持 拐弯冒泡 示例

support for custom DOM attributes

之前内置了HTML/SVG属性名白名单,自定义属性会被拦截并忽略掉,React 16去掉了这个限制

去掉该限制有2个原因,其一,这层内置的属性过滤对于非标准的(比如proposal阶段的)新属性和其它库/框架(比如Angular、Polymer)很 不友好 ;其二,bundle里要内置一份体积不小的属性白名单,维护起来还 挺麻烦

improved server-side rendering

号称比React 15 快3倍 (benchmark场景,某业务场景据说1.3倍),做了几件事:

注意 :React 16貌似也存在 一些DOM node复用的问题

However, it’s dangerous to have missing nodes on the server render as this might cause sibling nodes to be created with incorrect attributes.

P.S.具体要注意哪些危险场景,官方后面可能会给出专门的博客,暂时没有说清楚

reduced file size

React bundle瘦身(重构,扁平化打包策略,并换用rollup),体积小了30%

二.SSR

变化最大的应该是SSR,这次认真实现了一下(之前的SSR像是地上捡的)

1.新API

server侧新增了 renderToNodeStream, renderToStaticNodeStream 分别对应 renderToString, renderToStaticMarkup

client侧新增了 hydrate

2.宽松的一致性校验

client侧校验没那么严格了:

另外,还去掉了Server HTML结构上的checksum( data-react-checksum )以及id( data-reactid ),响应体大小会降低不少:

<!-- react 15 -->
<div data-reactroot="" data-reactid="1"
    data-react-checksum="122239856">
  <!-- react-text: 2 -->This is some <!-- /react-text -->
  <span data-reactid="3">server-generated</span>
  <!-- react-text: 4--> <!-- /react-text -->
  <span data-reactid="5">HTML.</span>
</div>
<!-- react 16 -->
<div data-reactroot="">
  This is some <span>server-generated</span> <span>HTML.</span>
</div>

3.性能优化

默认去掉了多余的 process.env.NODE_ENV 访问,不需要手动编译去掉

SSR不再创建一次性的virtual DOM,整个快了不少

支持stream,带来的性能优势如下:

4.不支持Error Boundary和Portal

React 16 SSR不支持 Error Boundary Portal

服务端子组件渲染出错,不会被Error Boundary拦住。 为了stream性能优势 ,牺牲了Error Boundary:

This is intentional / a known limitation. With streaming rendering it’s impossible to “call back” markup that has already been sent, and we opted to keep renderToString and renderToNodeStream’s output identical.

不仅 renderToNodeStream, renderToStaticNodeStream 不支持Error Boundary, renderToString 也不支持 ,如上面说的,为了保持输出结果一致,没有维护2套机制

P.S.关于SSR Error Boundary的更多信息,请查看 componentDidCatch doesn’t work in React 16’s renderToString

而Portal特性可能造成“回流”,与Error Boundary是一个道理,在stream机制下无法支持(想要往已经发送出去的stream里插入Portal内容,当然不可能)

三.Fiber

全新的核心架构,(花了2年)整个重写了组件渲染机制,最关键的特性是 异步渲染 (async rendering),实现了可调度渲染(彻底解决mount流程一旦开始就无法中断的问题)

重构过程

这样庞大的一个东西,伤筋动骨的重构执行过程很有意思。简单地说:

P.S.具体重构过程见 React 16: A look inside an API-compatible rewrite of our frontend UI library

所以 暂时不支持 异步渲染:

This initial React 16.0 release is mostly focused on compatibility with existing apps. It does not enable asynchronous rendering yet. We will introduce an opt-in to the async mode later during React 16.x. We don’t expect React 16.0 to make your apps significantly faster or slower, but we’d love to know if you see improvements or regressions.

优势

参考资料

作者:黯羽轻扬
原文地址:React 16, 感谢原作者分享。

发表评论