React Virtual DOM、Ember Glimmer和Incremental DOM技术哪家强_virtual dom incremental dom-程序员宅基地

技术标签: RIA  

原文链接React Virtual DOM vs Incremental DOM vs Ember’s Glimmer: Fight 
TooNaiveMan 翻译于2015/12/3


本文将探索3种构建动态DOM的技术,并通过一些基准测试对比3种技术的性能快慢,最后我会给出在项目中哪种技术更加适合以及为什么。
介绍
现在已经有许多DOM操作的框架和类库。在这些类库之中,专注于性能而被关注最多是React.js,Ember.js以及最新的Incremental DOM。React和Ember已经远不是简单的对DOM进行构建/更新,而Incremental DOM 专注在构建DOM树和动态更新。下面将对比测试这三个类库的快慢。

在深入细节之前,非web开发者可能会问什么是 DOM 操作,这里简单介绍一下。网页实际上是由不用元素构成的一个树形结构。元素按照HTML规范定义工作。通过组合这些元素,我们可以构建任意复杂的网站。而DOM树就是一个树形HTML元素的抽象表示,它由W3C规范定义并且被所有主流浏览器实现支持。

除了帮助将模型绑定到视图,这些类库能高效更新DOM,一般情形下的多次DOM操作会被自动合并成单次(或更少)的调用。比如某一次操作需要进行:

  1. 删除元素

  2. 添加元素

  3. 改变添加元素的属性

通过DOM接口进行如上操作会导致高开销的内容重新绘制和布局。通过虚拟模型就可以把上述分次操作合并成一次。

模板

用模板技术生成DOM很流行。开发中通过模板语法告诉编译器生成DOM树(或者HTML文档)。模板技术可以是HTML的扩展或者是全新设计语法。

本文介绍的三种技术并非都用了模板。比如React使用了JSX:一种Javascript的拓展语法,通过预编译的方式支持在Javascript里面插入类HTML的代码。然而Ember使用了一种叫Handlebars的模板语言。
Incremental DOM 并没有偏向特定的模板引擎,然而,Google赞助一个名叫Closure templates 的项目将被支持,Incremental DOM还可以和superviews.jsstarplate甚至JSX一起工作。

React.js 的虚拟DOM

React开发者对DOM操作引擎命名为虚拟DOM,她通过一系列的Javascript调用告诉类库生成一个内存的DOM树并且和数据的变动同步起来。虚拟DOM的核心是智能差量算法(smart deffing algorithm):当数据模型变动更新到内存DOM树上时,算法会生成同等效果,但最小需要更新DOM树的指令。所以在不同的状态下有两份内存DOM树。

声明:本文一些图出自:[excellent post explaining DOM manipulation libraries](http://teropa.info/blog/2015/03/02/change-and-its-detection-in-javascript-frameworks.html)
优点
  • 差量算法高效快速

  • 前端支持多种语法(JSX,hyperscript)

  • 对移动设备足够轻量

  • 发展迅速,关注度高

  • 可以脱离React使用(仅仅使用引擎)

缺点
  • 内存DOM导致高内存消耗

  • 没有区分静态和动态元素*

React最近在实现一个通过检测不变量来减少需要做差量化比较的元素。

Ember.js 的Glimmer

Glimmer是Ember.js最近的模板引擎,她借鉴引入了React的虚拟DOM技术同时保持了接口的一致性。需要指出的是开发者重写了整个引擎,并没有和虚拟DOM共享代码。

Glimmer区分了**静态****动态**的组件,因此减少了需要检测的元素数量。这个区别得益于handlerbar引擎的高表述性。
Glimmer另外区分其他方案的关键实现是对于元素节点的存储和比较,是被存放在一个简单的流对象(就是一个简单的对象队列)而不是完整的类DOM节点。这样如果要计算下次需要更新的节点,只要比较节点的值是否改变,如果没有改变就不需要进行下一步操作。

优点
  • 高效快速的比较算法

  • 引擎区分静态和动态元素

  • 100%对Ember接口兼容(现有Ember用户不用改变代码)

  • 轻量化DOM的内存表达方案

缺点
  • 之能在Ember使用

  • 只有一种前端选择

Incremental DOM

相比而言,Incremental DOM尝试通过简单的方案:与其维护DOM树完整的、或者轻量话的内存拷贝,当数据改变的时候,Incremental DOM直接在真正的DOM元素上做比较。大家可能问为什么,如果就这么简单那为什么其它技术没有采用这种方案。简单的说:所有的方案都是在内存和速度上做一个权衡。而Incremental DOM,通过去除DOM树拷贝来减少内存的占用,实际上确实脏检查导致了性能下降。节省的内存对于手机或者其他内存宝贵的设备来说非常关键。大家可以关注我的另一篇博文:our article on Incremental DOM

优点
  • 减少内存占用

  • 接口简单明了

  • 容易集成到其它的前端框架(当然需要一开始就以它作为后端引擎)

缺点
  • 速度相对较慢(这个是有争议的,看下面的测试结果)

  • 关注度和社区使用较少

性能测试

我们选择这篇博文里的 dbmonster test app来做测试。Dbmonster是针对数据库集群行为的场景模拟出在table里面进行大量的行更新,一来是被开发出来测试Ember的性能的程序。我们使用了最新的React,Ember 1.x 和 2.x(都使用了Glimmer)和Incremental DOM。所有的测试都跑在Linux环境的Chromium 46(Core i5-5200U CPU)。每种测试跑5遍然后取平均值。

在有大块和小块垃圾收集的场景中。Incremental DOM表现出了预期的高效。React紧随第二但是在琐碎垃圾收集场景中大幅落后Incremental DOM。有意思的是Ember 1 到 2 的改进还是比较大的。

Ember在布局和绘画操作中所花时间这个场景中表现突出。Incremental DOM由于牺牲性能获取内存,不出意料的排在最后。React目前来看比较平衡。

这特图标显示出Chrome的丢帧数(不响应导致的停止绘画)。丢帧的结果是帧率低和画面停顿感。在这个场景中,Incremental DOM再次突起,更少用于处理GC的时间片段使得用户绘画的时间更多。React和Ember紧随其后。
一个没有反应在图标中的有趣的现象是,主观上会感觉Incremental DOM的响应更快。通过观察收集的数据,发现Incremental Dom相比对比技术的Javascript操作更少。当然,这和Incremental DOM是一个单纯的DOM操作类库,而React和Ember处理的东西更多:时间,数据传输等等。一个不用React的虚拟DOM的测试会很有意思。
我们看看最后完整总结的结果

这里有测试所用的代码。你需要安装ChromeDriver和所有Node.js的依赖(json2csv,brower-perf),然后运行命令 node run-benchmarks.js 。最后的测试结构卸载data.json(完整)和results.csv(总结)。

题外话:在Auth0使用React.js

在Autho,我们一直在评估最适合我们的技术。我们用React.js开发了 Passwordless Lock library。因为React没有对model技术的依赖使得它成为我们最好的选择,在其他方面,React在速度,内存占用,集成难度和文档、支持取得了一个很好的平衡。

注册使用我们的Passwordless Lock library或者看看代码
结论
虚拟DOM,Glimmer和Incremental DOM都是动态操作DOM树的优秀方案。React.js的快速发展和轻量化是许多项目的不二选择。虽然高内存占用对于内存吃紧的移动设备上运行的大型网站会有问题,但是随着移动设备的硬件发展,这个问题正在逐步淡化。Incremental DOM花小钱办大事的效果让人眼前一亮,我们期望她能集成到Closure和其他库中。React和Ember在各自的实现方法中取得了很好的平衡。
当选择这几个技术的时候,最好关注技术的成熟度和是否容易集成。除非你对DOM的操作巨频繁(意思就是一般情况下,性能问题没那么突出),如果这样,请仔细的研究播客的结果并且针对你的场景生成测试数据。

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/yczz/article/details/51494762

智能推荐

python编码问题之encode、decode、codecs模块_python中encode在什么模块-程序员宅基地

文章浏览阅读2.1k次。原文链接先说说编解码问题编码转换时,通常需要以unicode作为中间编码,即先将其他编码的字符串解码(decode)成unicode,再从unicode编码(encode)成另一种编码。 Eg:str1.decode('gb2312') #将gb2312编码的字符串转换成unicode编码str2.encode('gb2312') #将unicode编码..._python中encode在什么模块

Java数据流-程序员宅基地

文章浏览阅读949次,点赞21次,收藏15次。本文介绍了Java中的数据输入流(DataInputStream)和数据输出流(DataOutputStream)的使用方法。

ie浏览器无法兼容的问题汇总_ie 浏览器 newdate-程序员宅基地

文章浏览阅读111次。ie无法兼容_ie 浏览器 newdate

想用K8s,还得先会Docker吗?其实完全没必要-程序员宅基地

文章浏览阅读239次。这篇文章把 Docker 和 K8s 的关系给大家做了一个解答,希望还在迟疑自己现有的知识储备能不能直接学 K8s 的,赶紧行动起来,K8s 是典型的入门有点难,后面越用越香。

ADI中文手册获取方法_adi 如何查看数据手册-程序员宅基地

文章浏览阅读561次。ADI中文手册获取方法_adi 如何查看数据手册

React 分页-程序员宅基地

文章浏览阅读1k次,点赞4次,收藏3次。React 获取接口数据实现分页效果以拼多多接口为例实现思路加载前 加载动画加载后 判断有内容的时候 无内容的时候用到的知识点1、动画效果(用在加载前,加载之后就隐藏或关闭,用开关效果即可)2、axios请求3、map渲染页面4、分页插件(antd)代码实现import React, { Component } from 'react';//引入axiosimport axios from 'axios';//引入antd插件import { Pagination }_react 分页

随便推点

关于使用CryPtopp库进行RSA签名与验签的一些说明_cryptopp 签名-程序员宅基地

文章浏览阅读449次,点赞9次,收藏7次。这个变量与验签过程中的SignatureVerificationFilter::PUT_MESSAGE这个宏是对应的,SignatureVerificationFilter::PUT_MESSAGE,如果在签名过程中putMessage设置为true,则在验签过程中需要添加SignatureVerificationFilter::PUT_MESSAGE。项目中使用到了CryPtopp库进行RSA签名与验签,但是在使用过程中反复提示无效的数字签名。否则就会出现文章开头出现的数字签名无效。_cryptopp 签名

新闻稿的写作格式_新闻稿时间应该放在什么位置-程序员宅基地

文章浏览阅读848次。新闻稿是新闻从业者经常使用的一种文体,它的格式与内容都有着一定的规范。本文将从新闻稿的格式和范文两个方面进行介绍,以帮助读者更好地了解新闻稿的写作_新闻稿时间应该放在什么位置

Java中的转换器设计模式_java转换器模式-程序员宅基地

文章浏览阅读1.7k次。Java中的转换器设计模式 在这篇文章中,我们将讨论 Java / J2EE项目中最常用的 Converter Design Pattern。由于Java8 功能不仅提供了相应类型之间的通用双向转换方式,而且还提供了转换相同类型对象集合的常用方法,从而将样板代码减少到绝对最小值。我们使用Java8 功能编写了..._java转换器模式

应用k8s入门-程序员宅基地

文章浏览阅读150次。1,kubectl run创建pods[root@master ~]# kubectl run nginx-deploy --image=nginx:1.14-alpine --port=80 --replicas=1[root@master ~]# kubectl get podsNAME READY STATUS REST...

PAT菜鸡进化史_乙级_1003_1003 pat乙级 最优-程序员宅基地

文章浏览阅读128次。PAT菜鸡进化史_乙级_1003“答案正确”是自动判题系统给出的最令人欢喜的回复。本题属于 PAT 的“答案正确”大派送 —— 只要读入的字符串满足下列条件,系统就输出“答案正确”,否则输出“答案错误”。得到“答案正确”的条件是: 1. 字符串中必须仅有 P、 A、 T这三种字符,不可以包含其它字符; 2. 任意形如 xPATx 的字符串都可以获得“答案正确”,其中 x 或者是空字符串,或..._1003 pat乙级 最优

CH340与Android串口通信_340串口小板 安卓给安卓发指令-程序员宅基地

文章浏览阅读5.6k次。CH340与Android串口通信为何要将CH340的ATD+Eclipse上的安卓工程移植到AndroidStudio移植的具体步骤CH340串口通信驱动函数通信过程中重难点还存在的问题为何要将CH340的ATD+Eclipse上的安卓工程移植到AndroidStudio为了在这个工程基础上进行改动,验证串口的数据和配置串口的参数,我首先在Eclipse上配置了安卓开发环境,注意在配置环境是..._340串口小板 安卓给安卓发指令