JavaScript 框架 TodoMVC 大小比较

2025-05-28

JavaScript 框架 TodoMVC 大小比较

JavaScript 框架的大小实际上是一个非常难以估计的事情。

甚至连确定运行时的大小都不太清楚。你可以去 bundlephobia.com,但那里的大小可能会有误导性。使用 tree-shaking 时,并非所有代码都包含在内。Bundlephobia 也不包含子模块。诸如svelte/motion或 之类的东西preact/hooks

不仅要考虑运行时的大小,还要考虑组件代码的大小。并非所有组件都相同。每个框架中的模板编译方式也不同。Vue 的创建者 Evan You对 Svelte 和 Vue 进行了比较,非常有启发性。

我决定采用他的流程和方法,并将其应用于PreactReactSolid。那么,让我们开始吧。

我是 Solid 的作者,所以请注意我可能表现出的任何偏见。我会尽量保持公平。


设置

该测试会检查库(供应商)包的大小以及TodoMVC的组件代码。每个框架都有一个版本,并且要求都安排得当,因此每个版本都相对相同。

我最初考虑只使用官方的演示版本,但 Preact 和 React 仍然使用较大的类组件,无法代表现代开发方式。这确实意味着 Preact 的库大小有所增加(3.81kb -> 4.39kb),虽然其主包中不包含 Hooks,但对于本次测试来说绝对值得。最终,我找不到满意的 Hooks 实现,因此我基于 Solid 的实现版本,自己动手实现了一个。您可以在这里找到所有实现。

供应商代码块从Vite中提取,它支持所有已测试的框架。对于组件代码,我使用了VueSvelteSolid的 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 就够了)。所以这个比较只能维持现状了。

希望这能给你足够的思考空间,直到下次讨论规模问题。或许到那时,考虑到MarkoQwik彻底颠覆了我们测量发送到浏览器的 JavaScript 框架代码的方式,这将是一个完全不同的话题。


本文中使用的 TodoMVC 示例的完整源代码可在此处找到

文章来源:https://dev.to/this-is-learning/javascript-framework-todomvc-size-comparison-504f
PREV
Marko 用于网站,Solid 用于应用程序
NEXT
组件是纯开销 你的框架是纯开销 组件 DX > 性能消失的组件 未来是无组件的