JavaScript 框架 TodoMVC 大小比较
JavaScript 框架的大小实际上是一个非常难以估计的事情。
甚至连确定运行时的大小都不太清楚。你可以去 bundlephobia.com,但那里的大小可能会有误导性。使用 tree-shaking 时,并非所有代码都包含在内。Bundlephobia 也不包含子模块。诸如svelte/motion
或 之类的东西preact/hooks
。
不仅要考虑运行时的大小,还要考虑组件代码的大小。并非所有组件都相同。每个框架中的模板编译方式也不同。Vue 的创建者 Evan You对 Svelte 和 Vue 进行了比较,非常有启发性。
我决定采用他的流程和方法,并将其应用于Preact、React和Solid。那么,让我们开始吧。
我是 Solid 的作者,所以请注意我可能表现出的任何偏见。我会尽量保持公平。
设置
该测试会检查库(供应商)包的大小以及TodoMVC的组件代码。每个框架都有一个版本,并且要求都安排得当,因此每个版本都相对相同。
我最初考虑只使用官方的演示版本,但 Preact 和 React 仍然使用较大的类组件,无法代表现代开发方式。这确实意味着 Preact 的库大小有所增加(3.81kb -> 4.39kb),虽然其主包中不包含 Hooks,但对于本次测试来说绝对值得。最终,我找不到满意的 Hooks 实现,因此我基于 Solid 的实现版本,自己动手实现了一个。您可以在这里找到所有实现。
供应商代码块从Vite中提取,它支持所有已测试的框架。对于组件代码,我使用了Vue、Svelte、Solid的 REPL 和 Terser REPL 进行压缩。对于 Preact 和 React,我使用 rollup 生成编译后的代码。
这个过程比我通常做的基准测试要宽松得多。说实话,代码风格和可用的演示代码确实存在一些差异。但我认为它仍然大致一致。
结果
第一步是获取每个组件和供应商代码的大小。TodoMVC 是一个相当合理的例子,因为它涉及基本的状态处理、条件和循环渲染、表单,甚至序列化到本地存储。这样一来,我们就能比 Bundlephobia 更好地了解每个框架的基本大小。
预行动 | 反应 | 坚硬的 | 苗条 | Vue | |
---|---|---|---|---|---|
组件大小(brotli) | 1.21kb | 1.23kb | 1.26kb | 1.88kb | 1.10kb |
供应商规模(brotli) | 4.39kb | 36.22kb | 3.86kb | 1.85kb | 16.89kb |
一般来说,可变状态比不可变状态更小,并且无 VDOM 的库会为其模板生成更多 JavaScript。Vue 的组件生成的代码最少,略胜 JSX 库和 Svelte。
Svelte 的运行时确实很小,只有 1.85kb。Preact 的核心可能比 Solid 要小,但加上 hooks 之后,这个响应式框架最终变得更小了。
由此,很容易计算出 N 个 TodoMVC + vendor chunk 下每个框架的大小。
1 | 5 | 10 | 20 | 40 | 80 | |
---|---|---|---|---|---|---|
苗条 | 3.73kb | 11.25kb | 20.65kb | 39.45kb | 77.05kb | 152.25kb |
坚硬的 | 5.12kb | 10.16kb | 16.46kb | 29.06kb | 54.26kb | 104.66kb |
预行动 | 5.60kb | 10.44kb | 16.49kb | 28.59kb | 52.79kb | 101.19kb |
Vue | 17.99kb | 22.39kb | 27.89kb | 38.89kb | 60.89kb | 104.89kb |
反应 | 37.45kb | 42.37kb | 48.52kb | 60.82kb | 85.42kb | 134.62kb |
虽然 Svelte 一开始领先,但很快就被 Solid 超越,并将桂冠传给了 Preact。Preact 在榜单中占据了相当大的份额,最终 Vue 胜出。
因此将拐点放在表中:
苗条 | 坚硬的 | 预行动 | Vue | 反应 | |
---|---|---|---|---|---|
苗条 | - | 3.2 | 3.8 | 19.3 | 52.9 |
坚硬的 | - | - | 10.6 | 81.4 | 1078.7 |
预行动 | - | - | - | 113.6 | - |
Vue | - | - | - | - | - |
反应 | - | - | - | - | - |
这是每个框架都比下一个更大的点。从 0-3 个 TodoMVC 开始,Svelte 是最小的。从 3 到 10 个 TodoMVC 开始,Solid 是最小的。从 10-113 个 TodoMVC 开始,Preact 是最小的。而超过 113 个 TodoMVC 的 Vue 是最小的。
Preact 和 Vue 从未与 React 产生过交集,而 Solid 即便与 React 产生交集,也不过是在大约 1080 个 TodoMVC 之后。总而言之,这与我们在演示和基准测试中看到的情况非常一致。对于 Hello World 和 TodoMVC 来说,Svelte 始终是最小的;对于“真实世界”演示以及人们基于流构建的简单网站类型来说,Solid 是最小的;而对于规模较大的项目来说,Preact 则更胜一筹。
分析
TodoMVC 作为单个组件来说体积较大,典型的实现通常包含 3-4 个组件,因此我不认为这些组件数量一定是组件数量。但很容易看出,每个框架都有其最佳使用场景。
页面大小的最大影响体现在初始页面加载阶段。其他代码拆分路由可以根据需要进行延迟加载,但初始页面加载是每个网站都需要预先承担的成本。如果您认同 Addy Osmani 的《JavaScript 的成本》系列和 Alex Russell 的《你能负担得起吗?:现实世界的 Web 性能预算》中的观点,那么我们真的应该将初始页面加载 JavaScript 的大小控制在 130kb 以下。
如果这是一个单页应用 (SPA),预算中应该包含数据获取、状态库和路由器。对于大多数框架来说,这通常会额外增加 20 到 25kb 的 JS 代码。像 Svelte、Solid 和 Vue 这样的响应式框架可能内置了状态管理,但即便如此,考虑到使用第三方工具库进行格式化,我认为我们的框架和组件代码应该小于 100kb。
在该预算下,每个框架允许多少个 TodoMVC?
反应 | Vue | 预行动 | 坚硬的 | 苗条 | |
---|---|---|---|---|---|
10kb | - | - | 4.6 | 4.7 | 4.3 |
20kb | - | 2.8 | 12.9 | 12.4 | 9.7 |
40kb | 3.1 | 21 | 29.4 | 28.7 | 20.3 |
70kb | 27.5 | 48.3 | 54.2 | 52.5 | 36.3 |
100kb | 51.9 | 75.6 | 79.0 | 76.3 | 52.2 |
在 100kb 大小下,React 和 Svelte 实际上几乎完全相同。而 Vue、Preact 和 Solid 则紧随其后,可用预算几乎高出 33%。但这已经是上限了。在 40kb 大小下,Preact 和 Solid 可以构建相当庞大的网站,并且与 Vue 和 Svelte 具有类似的优势,在这个范围内,React 甚至不是一个真正的选择。
Alex 的目标是在较慢的设备和网络上实现 5 秒的 TTI。对于电商等行业来说,这个目标应该更接近 3 秒。70kb - 25kb = 约 45kb 的预算。像 React 这样更大的库如何与之竞争?
React Server 组件在 React 当前运行时的基础上增加了约 8kb 的内存,这已经让它们失去了竞争力。像Astro这样的多页面元框架消除了对路由的需求,并且可能还不需要其他第三方库,可能勉强够用。但即使是像 Astro 这样强大的工具,在需要加载 JavaScript 时,也会占用约 9kb 的内存。
但对于其他应用来说,还有更大的发挥空间。一个简单的网站可能在一个页面上只有 5-10 个“岛”,任何选项都很好。即使是像 Preact、Svelte 或 Solid 这样的小型库的完整 SPA,也完全在可接受的范围内。
结束语
在重要的范围内,所有框架都相当可比。对于大型应用来说,Svelte 最终可能会在多个页面上加载更多 JavaScript,但其他框架的 JavaScript 加载速度足够接近,因此在大型应用中不会感觉到这一点。
总体来看,Preact 在大小方面仍然胜出。Solid 的规模非常接近,两者之间的差异几乎察觉不到,但 Preact 更值得肯定。React 的价格略高于小型应用或对性能要求较高的应用,但一旦应用规模足够大,其大小变化就不明显了。Vue 的规模介于两者之间,但最终在大型应用中,它发送的 JavaScript 代码量可能是最少的。
请记住,这个比较相当粗略,只能看作一个估计。我唯一遗憾的是没能抽出时间去研究更多库。不出所料,很多 TodoMVC 示例都是 MVC 风格编写的,这对于这个比较或使用像 Redux 这样的 store 来说并不公平。我自己也没打算写一堆(Preact 和 React 就够了)。所以这个比较只能维持现状了。
希望这能给你足够的思考空间,直到下次讨论规模问题。或许到那时,考虑到Marko和Qwik彻底颠覆了我们测量发送到浏览器的 JavaScript 框架代码的方式,这将是一个完全不同的话题。
本文中使用的 TodoMVC 示例的完整源代码可在此处找到
文章来源:https://dev.to/this-is-learning/javascript-framework-todomvc-size-comparison-504f