最近在浏览网页的时候意识到前端这两年没有出现一个好的JavaScript框架了。在这个不平凡的2020年结束之前,来看看2020年流行脚本库之间的性能对比。
什么Javascript框架最流行呢? 在这里就以Github上星级数排名20的JavaScript框架进行对比,用JS Framework Benchmark对它们进行比较。
声明:此比较在整个过程中很有趣,也可能具有教育意义。和往常一样,这里的每个库对于大多数事情来说都足够高效。如果有什么要强调的是,性能可以来自多种不同的技术。虽然可以将其用作参考,但应该独立验证各个用例的性能。可以在这里找到最新的官方结果。在此声明,比较只是客观,实际开发过程需要结合团队水平、协作情况、效率等综合考虑。
采用最新的谷歌浏览器Chrome 87
关键结果的JS Framework Benchmark
。它们在Fedora 33下的Core i7 Razor Blade 15上运行,且关闭缓解。
过滤掉了所有有问题的实现,然后获得了Github
星级数量前20的脚本库。对于具有多个版本的库,没有使用第三方库获取它们的最新版本和性能最高的变体。下面是Github
星级排名前20的脚本库的信息及星级情况。
注意:我将把
LitElement
实现用作lit-html
示例,因为标准示例已被标记为问题。开销应该最小,因为它是包装在单个Web组件中的原始lit-html
。
这是当前Web开发生态系统中相当不错的一部分。尽管Github Stars
并不是全部,但比较中有100多个库,因此需要选择相对比较流行的。
每个库将在3个类别中进行比较:
此外,将框架分为4组,以将它们与原始性能同级进行最佳比较。但是,将在所有三个方面对脚本库进行排名。
在每个组中,将存在参考Vanilla JavaScript
条目。使用所有最佳技术,此实现都经过了最优化,以达到最佳性能。它将作为所有比较的基准。
这是最大的组,由一些最受欢迎的脚本库组成。还有许多来自Facebook、Google、eBay和阿里巴巴等公司支持的公司。这些脚本库要么在某个方面不太注重性能,要么突出某个领域的性能,而在其他方面表现不佳。
这里有很多红色和橙色,但请记住,这些库平均仅比我们在此处使用的痛苦手工制作的命令式Vanilla JavaScript示例慢大约2倍。 400ms与200ms有何不同?
在原始性能方面,React是该组的领导者。考虑到架构的差异性,尽管它从未间断,但React、Marko、Angular和Ember的整体差距不大。仍然是React,这是React Hooks的实现,在这里是领导者。对于所有指向额外的函数创建并坚持使用类的人来说,性能参数不在您身边。React Hooks是使用React的最高效的方法。
这里的大多数库要么幼稚的列表排序导致交换行性能确实很差,要么创建成本很高。Ember是这种情况的极端案例,因为它的更新性能比该组中的其他成员要好得多,但在某些最坏的情况下却是创建过程。
最慢的库(Knockout,Ractive和Alpine)都是具有类似架构的细粒度反应库。Knockout和Ractive(也由Svelte的作者Rich Harris撰写)来自2010年初VDOM库主导之前。我还怀疑Alpine是否期望使用其JavaScript方法来渲染1万行。在比较之后,我们将看不到另一个纯细粒度的反应式库。
接下来,我们将主要基于库包的大小来比较类别的启动指标。
此处清单变化很大。在Alpine表现最差的地方,我们可以看到它拥有最小的bundle大小和最快的启动时间。Marko(来自eBay)紧随其后,其次是Rax(来自阿里巴巴)。所有这三个库都是为服务器端渲染而构建的,主要是通过更轻松的客户端交互来实现的。这就是为什么他们在性能方面处于第4组,却在这里领先于启动的原因。
表格的后半部分是我们在基准测试中拥有的最大的包软件,以Ember结尾,是任何其他实现的两倍以上。我不知道为什么要花费超过半兆字节才能呈现此表。但这确实会损害启动性能。
我们要看的最后一类是内存消耗。
内存倾向于反映我们已经看到的模式,因为它对性能有很大的影响,而较大的库则倾向于使用更多的内存。Alpine,Marko和React引领潮流。老化的细粒度反应库使用最多的Ember。Ember是巨大的。仅在页面上渲染6个按钮之后,它已经使用了比Vanilla在整个套件中使用的更多的内存。
通常,该组在GitHub上代表30万颗星,可能是NPM下载量的最大部分,但Marko和Alpine在此人群中的平均排名最高。在性能方面,React排名第三,仅次于他们。
在这些框架中,您可以知道已经考虑了性能。他们意识到规模,并且在创建和更新成本之间找到了平衡。我们看到了各种各样的方法。Yew中的一个Web Assembly框架(用Rust编写),LitElement中的一个Web组件。
事不宜迟,让我们看看它们的工作方式。
分数已经提高了一点,我们看到的差距甚至更大。Preact是该组中性能最高的,仅增加了LitElement。Vue 3和Riot捆绑在一起,这两个库都位于中间,它们的历史都包括反应性和VDOM。Mithril是最早将性能放在首位的VDOM库之一,Yew是唯一的WASM库尾部。
在性能方面,所有这些库都是相似的。在这堆中没有纯的反应库。它们都使用自顶向下的呈现方式,无论是VDOM还是简单的Tag Template Literal diff。与上一组相比,它们的对帐清单更智能(请参阅交换行性能)。但是,大多数仍然具有某些最慢的选择行性能。
Yew是例外,但在其他方面则较慢。让我们看看其余的测试是否有帮助。
情况有所改观,但在启动指标方面,Preact仍然处于领先地位。Yew是这一堆中唯一真正的大型的脚本库。WASM库确实倾向于更大的一边。
再次,我们看到一种结果配对。Vue是仅次于Yew的第二大脚本库。Preact和Riot非常紧凑。Mithril和LitElement在中间
Preact是React的4kb替代品,绝对是我们迄今为止所看到的最小的库。但是最小的库仍在继续。尽管如此,这个范围内的任何库都不应该太关注它们的包大小。
Yew这次赢了。在所有经过测试的框架中,它具有最小的内存占用量。WASM库在这方面表现也很好。其他都非常接近。Mithril和Preact是最差的,但差距不大。
从这里也没什么可聊的了。可能会认为LitElement示例可能比其他非yew库更轻,因为它不像其他库那样使用虚拟DOM。但正如我们稍后将看到的,VDOM并不意味着更多的内存。
Riot和Preact平均排名最好,其次是LitElement,排名第三。Riot虽然表现不佳,但在这个小组中没有任何弱点,最终在比较中胜出。但是,对这些框架中的任何一个都不会感到失望。通过WASM和Web组件,它们代表了许多人认为的Web的未来。
这个组的脚本库是竞争激烈的。我们拥有大多数被称为编译语言的库。每一种都有自己的特色。我们拥有不变的结构化Elm,受Ruby启发的Imba和“消失的” Svelte。
注意:并不是每个人都熟悉Svelte以前的“消失的框架”绰号。它描述了从输出中基本进行自我编译的能力。
奇怪的是HyperApp,它与其他应用程序完全相反。没有编译器。没有模板。只需h
个功能和一个最小的Virtual DOM
好吧,最小的虚拟DOM胜出。与最近的言论相反,事实证明虚拟DOM不仅是性能不佳的秘诀,而且编译并没有给其他库带来帮助。
在已编译的库中,我们实际上看到了3种不同的方法来渲染所有具有大约相同的平均性能。
您应该注意,虚拟DOM库的选择行最差,因为这是它们的额外工作所在。但是这些库还具有更快的初始渲染。如果您仔细观察到目前为止的结果,您应该注意到与响应式库相比,虚拟DOM库之间的共享特性。但除此之外,性能还很严格。
因此,让我们继续。我们的编译器如何调整启动时间/包大小?
好吧,正如您所看到的那样,这个小的虚拟DOM库不仅性能更高,而且比其他的更小。实际上,HyperApp是我们所有库中最小的实现。编译器无法赢得成功。
它和Svelte都比我们的Vanilla JavaScript参考构建小。那怎么可能?以一种更可重用的方式编写更少的代码来编写抽象。Vanilla JS实现针对性能而非大小进行了优化。
Elm在这一组中仍处于竞争规模。然而,Imba开始进入group 4中的一些库的范围。
好了,来对比内存,编译器大放异彩的最后机会。
内存接近,几乎是平局,但是Svelte最终为编译器赢得了胜利。对虚拟DOM的一些甜蜜的报复显示它比它更小,更快。
老实说,所有这些库都具有出色的内存配置文件。现在应该很清楚,更少的内存和更好的性能之间的关系。
不要相信炒作?
不。更多的事情比表面上看起来复杂。精心设计的系统,无论是运行时还是编译时,或者无论采用何种技术方法,都可以制成高性能的系统。
HyperApp是该组的明显赢家,其后是Svelte,其次是Elm和Imba。通过这种对性能的专注,您知道这些库在大多数情况下都可以提供,并且始终显示在基准测试的顶部。
在某种程度上,这可能被称为“令人眩目的快”,我相信它曾经是这些库的标语之一。如果你要跟踪的话,现在只剩下2个脚本库了。事实上,这个类别中有少数脚本库在不断地挑战边界。但流行的只有2种。它们比手工优化的原始Vanilla JS平均慢不到20%。
这是值得一看的。这里我们有两个库,如果看它们的代码,它们可能被认为是兄弟,但使用的方法完全不同。Inferno是世界上性能最好的虚拟DOM库之一。没错,前5名中有3个是虚拟DOM库。select row测试的放缓可以看作是证据。
另一方面,Solid使用细粒度的反应性,例如第4组中最慢的旧库。重新出现此技术的位置很奇怪,但正如我们所见,Solid解决了它们的弱点。创建时间与更新时间一样快。与Vanilla JavaScript的5%差距令人难以置信。
奇怪的是,Inferno和Solid的共同点是JSX模板和React受启发的API。对于所有其他具有优化的自定义DSL的库,也许您不会期望在性能的顶峰找到任何东西。但是,正如HyperApp所示,某些事情对性能的影响比人们想象的要小。
Solid将HyperApp和Svelte作为第三个库加入,其库比Vanilla JS实现小。但是Inferno也不是懈怠。
似乎性能库较小时,有时添加更多代码可以提高性能。更好的列表协调算法,更明确的防护措施,更精细的更新。
Inferno可能比前几组中的某些库更大,但它仍然是一个10kb以下的库,在性能上几乎胜过所有。
在那里。除了Yew及其对WASM的使用以外,它们是整个竞争中最低的内存消耗框架。考虑到他们的表现,这并不奇怪。
这种内存消耗数字反映了对对象的非常仔细的考虑,并创建了闭包。其中很多确实来自两个库都进行的定制JSX转换。
内存性能的提高对Solid尤为重要,因为Solid与大多数细粒度的反应式库一样,都将CPU开销换成了内存消耗。在这种比较中,能够征服内存开销是Solid如何采用与大多数最慢的库类似的技术并使之成为最快的方法的很大一部分。
天空是极限。
…或者说Vanilla JavaScript是。但是我们这里的声明性库性能如此之差,您永远都不会知道它们之间的区别。当使用DOM时,我们要认真考虑要面对的问题,许多不同的技术可以有效地渲染DOM。
我们在这里看到它。Solid凭借十年前被认为是古老而缓慢的技术而获得了性能冠军,而Inferno再次证明了Virtual DOM不能有效地完成任何工作。
在构建JavaScript前端时,我们有很多选择。这只是快速了解框架带来的性能开销。当涉及到应用程序中的实际性能时,用户代码具有更大的影响。
但是,我真正想在这里打动的是,测试您的解决方案并了解性能是很重要的。现实总是与营销不同。虚拟DOM不能保证很慢。不能保证编译器会产生最小的包。自定义模板DSL不能保证是最佳的。
最后,我将为您提供完整的表,将所有库一起显示。仅仅因为图书馆快要结束了,并不一定意味着它很慢,但是与这些竞争激烈的竞争对手相比,它的得分更差。
单个图表中的所有框架。
性能
启动
内存
所有结果都添加到一个列表中(第1名获得20分,最后1名获得分)。在平局的情况下,成绩优先。