VirtualDOM已死?夸大后的谣言真可怕……

552 篇文章 2 订阅

全文共4528字,预计学习时长13分钟

来源:Pexels

 

理想很丰满,现实很骨感。

 

在科学界,这句话再适用不过。

 

最近阅读了几篇文章,文章的观点非常神奇,甚至到了荒唐地步,但却有来源支撑,详细调查后发现,支撑这些观点的居然是一些会议演讲的轶事。

 

其实并不是所有观点都错位了,只是缺乏证据和理由。可能有一天会得到正确的观点,但不是今天。

 

随着新年的到来,现在正是展望未来的好时机,为此我们讨论剖析了过去一年来出现的5个常见的“神话观点”。

 

神话一:消失的框架

 

来源:Pexels

 

笔者喜欢这一点。

 

自Virtual DOM以来,这是前端网页中最好用的市场营销用语,它正在帮助Svelte迅速进入市场。这很夸张。总有一个运行时间。运行时间可以很小,但必须有某种东西才能触发变化。而且所有库都附带纯JS、HTML和CSS。真正的英雄是Tree Shaking,这是一种静态分析导入语句以消除无效代码的过程。基本上,不导入的代码不需要包含在最后的捆绑包中。使用编译过程,需要做的就是查找标识符,然后添加导入语句,Tree Shaking是最佳方式。描绘这个过程并不难。编译器会遇到诸如#each之类的特定助手,并决定包括列表映射代码。不要相信笔者会在已编译的Svelte代码中寻找import语句。import语句就在那里。

 

现在通过编译,可以减少捆绑运行时间对代码的需求,因为可以对模板进行硬编码,实际上是展开循环。但是,一旦遇到了常见的模式,抽象的大小实际更有效,而在开发人员知道前,运行时间很小。现在,将任何足够简单的库与Tree Shaking结合使用,都可以产生相同的结果,但可能不太流畅。反应式库通常会更小,但是有的Virtual DOM库甚至可以产生等效或更小的捆绑包。也许应该考虑集中精力使有价值的事物消失。

 

神话二:调度意味着更好的性能

 

这并不时新,但会不断流行。

 

React 的Concurrent Mode只是制作几乎毫无意义的动画演示的最新趋势。为什么说大部分都毫无意义呢?

 

有意义的性能受到帧速率上限的限制。几乎所有演示都使用requestAnimationFrame,否则就需要做不必要的工作。因此,通常应对这种情况的唯一方法就是提出一些荒谬的方案。但是,这就意味着仅在极端情况下测试库——当库以最坏的方式受到限制时。这是有一定道理的。在资源有限的情况下,正常降级对低功耗设备可能很重要。但是,库如何摆脱束缚呢?想办法减少工作量。这不再是提高性能的练习,而是如何缩减工作量以提供更好的用户体验。

 

这是一个非常崇高的目标,但会带来一些有趣的副作用。检测和调度需要成本。显然比DOM需要的要少。但是,库中的渲染越重,则需要干预的时间越早。这成为了一种自我实现的预言。所有库都可以使用更多诸如requestAnimationFrame这样的调度技术。

 

因此,尽管阻塞主线程不利于交互性,但是很难一概而论地指出性能和阻塞量之间的最佳结合点。只有当超出硬件可以支持的极限时,人才会注意到这点,那么最合适的降级方法是什么呢?笔者通过SierpinskiTriangle Demo在办公室对不同调度算法的视觉反应进行了测试,结果很不一致。明显没有更好的选择。而使用Suspense切换选项卡上的延迟加载状态,在视觉效果是一致的。

 

目前使用的通用技术是基于最后期限和排队的概念。requestAnimationFrame和requestIdleCallback一个鲜为人知的功能在于,使用提供的回调信息可以确定需要使用多少时间。可以根据可用时间来管理工作,让用户在调度上更加明智。可惜的是,并不存在任何良方,有时更快即更好。

 

笔者希望这能够揭穿2019年关于前端的一些常见神话。笔者并不是要做一个反对者,因为笔者了解到,这其中很大一部分来自对未来的展望。尽管个人认为这些环绕技术具有很大的潜力,但笔者提醒自己要领先一步,因为这种热情尤其是在不基于具体现实的情况下会引起毫无根据的猜测,导致人们相信Virtual DOM的速度比2014年的实际DOM速度快。

 

是的,并没有快很多……

 

神话三:对于Web UI来说,Web Assembly更快

 

永远不会出现故障的一个常数是:JavaScript,永远不要低估它。但在笔者看来:永远不要低估DOM的成本。DOM非常昂贵。到目前为止,大多数人都知道使用DOM的成本,因为它会导致重排和重绘。而且,甚至读取会影响布局的属性也会导致过早回流。但是,使用DOM的其他属性也会带来巨大的成本。任何种类的树遍历都几乎与创建DOM节点一样昂贵。使用DOM进行任何操作都会产生额外的费用。

 

不幸的是,对于其他技术而言,成本甚至更高。

 

Web Workers会是一个救星,但他们无法访问DOM,因此尽管具有许多性能优势,但并未对Web UI产生有意义的影响。WASM具有类似的限制。当停留在WASM中时,WASM的速度比JavaScript快得多,但是越需要过渡到JavaScript API时,速度就越慢。

 

当前,这是访问DOM的唯一方法。随着Web绑定的引入,这一局面最终将发生改变。这是最近几年做的一些工作,当规范最终发布时,可以看到一些巨大的收益。到今天为止,不仅普通单纯的 js在执行DOM渲染时更快,而且某些数据驱动的高级库比最快的低级WASM性能更佳(请参阅https://github.com/krausest/js-framework-benchmark)。更高级别的WASM实现可能会产生更大的成本。因此,从长远来看,最新的WASM UI库性能是最好的。

 

神话四:网页组件可以替换框架或库

 

Web组件是一系列技术,仅使用HTML元素即可使HTML、CSS和JavaScript以可重用的方式实现模块化。这些技术为DOM添加了以前没有的功能,以实现如下目标:包括模板、CSS封装、元素生命周期挂钩(包括属性监视)和子元素插入。表面上看,这些都是可以通过UI框架实现的相同功能,最终可能会得到组件。那么,它们必须等效吗?

 

并不需要。一个是用于解决一般问题的本机工具,另一个是一组可以提高开发应用程序效率的自定义功能。这种困惑是可以理解的。有时,笔者甚至不确定参与编写建议的人员是否清楚界线在哪里。一些建议看起来像是下一个框架的规范。

 

但在过去的6年里,笔者一直关注着这一问题,供应商之间达成共识的速度很快,显然,功能集越基础,就越有可能向前发展。关于它们应该扮演什么角色,仍然存在很多争论。比如,支持Native Built-Ins(扩展现有Elements的能力)中并没有获得完全的支持。仅此一点就意味着,某些人认为这些不适用于设计系统。

 

那么它们有什么用呢?

 

来源:Pexels

 

似乎可以用于微型前端或小部件打包。用户可以设定自己的可访问性、本地化和表单处理功能,并设计自己的元素。需要明确的是,这与React组件并不相同。这些组件可以模块化,但并没有更改传播或有效渲染。它们的边界较明显,代表了整个生命周期内的封装隔离。每个人都可以将自己的UI库相邻放置。实际上,几乎所有产生网页组件库都是这种性质的库,需要学习框架和库。可以使用单纯的DOM API,但现在也可以在没有网页组件的情况下进行操作。当心不要被骗。可以将组件与已经熟悉的库一起使用,例如使用Angular Elements、Svelte或Vue导出自定义元素,或者与正在学习的库一起使用,例如Polymer、Stencil、Heresy或LitElement。

 

什么都没有变。使用这些库并不会突然支持开放的网络。实际上,最自由的方法可能是诸如SkateJS之类,它真的没发布框架,而是可以使用任何现有的框架。该库仅用于使API表面均匀化,并允许用户按照自己的方式运作。然而,大家仍在使用框架/库组合。

 

神话五:Virtual DOM是纯开销

 

笔者不能否认这不是事实。但是,这句话具有误导性。不是一切普通js都是纯开销。而且编译也不仅是为了优化代码。如神话二所述,仍然存在运行时间。因此,无论如何攻击它,都需要管理DOM的更新和更改。通常,所有现代数据驱动的UI库的工作方式无外乎以下三种*,每种方式都有自己的优缺点。人们可以创建每种方法的有效版本。实际上,已经存在着一些库,这些库在流行库的功能范围之外还展示了每种方法的大小和性能特征(请参阅https://github.com/krausest/js-framework-benchmark)。

 

Virtual DOM与其他方法一样,是一种完全可行的方法,仍然是在库中最受欢迎的使用方法,甚至权衡了产生网页组件的库。大多数基准测试都是通过库在单个组件中完成所有工作的方式进行设置的。在实际项目中,可以将其模块化为多个组件。这也会产生成本,但是对此讨论得不多。Virtual DOM通常能比其他方法更好地在更多组件上扩展。因此,人们对实际性能的看法可能会不一致。

 

笔者认为,不选择使用Virtual DOM的原因并不在于其性能或规模。而是用户更喜欢开发人员体验的扩展——组合模式,可变性与不可变性、代码结构等。但是,仅仅因为某些技术手段存在困难,并不意味着它不可实现。React的 Fiber和Hooks表明,Virtual DOM库的行为几乎类似于反应式库。当然,KnockoutJS在2010年就具备了这些功能,但这并没有削弱其中的潜力。

 

这里的三种方法是VirtualDOM、DOM协调和响应式。

 

VirtualDOM库的基础是使用生成区别于先前迭代的虚拟树,并修补DOM更新。VirtualDOM库使用不变性和引用相等性来进行捷径优化。但是,不变性导致大量克隆和内存分配。例如:React,Vue, Inferno。

 

DOM协调库在创建DOM节点时会隐藏绑定值。在每次更新时,都会与之前的值进行比较,并更新DOM。DOM协调库与VirtualDOM库相似,不同之处在于仅通过一次即可工作,并且仅在叶之间进行比较。但是,基于可变性,需要始终在叶上进行区分,因此在深度嵌套结构中优化捷径的方法较少。例如:Angular, Polymer, lit-html。

 

反应式库在创建DOM节点时会生成反应式图。这样,每个绑定上下文都可以与事件订阅相关联,以便在数据更新时,仅运行相关事件的处理程序。这种方法进行了一定的优化,因为它需要最小的差异,但是初始创建成本最大。例如:Svelte, Knockout, Solid。

来源:Pexels

 

留言 点赞 关注

我们一起分享AI学习与发展的干货
欢迎关注全平台AI垂类自媒体 “读芯术”

(添加小编微信:dxsxbb,加入读者圈,一起讨论最新鲜的人工智能科技哦~)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值