原文链接:www.lorenstew.art/blog/10-kan…
本想评估3个工作框架,结果建了10个。新一代框架(Marko、SolidStart、SvelteKit、Qwik)均能实现35-39ms的即时性能。真正的差异点?压缩后包体积从28.8kB到176.1kB不等。请根据优先级选择,而非微不足道的首次页面加载时间差异。
为啥这么做?
我的团队需要为即将开发的应用选择一个框架。要求很明确:它必须在移动设备上运行流畅。我们正在为实地工作的房地产经纪人打造工具。他们需要在开放看房现场、停车场以及信号不稳定的区域使用我们的应用。当经纪人站在潜在买家面前试图展现专业形象时,加载缓慢的应用会让他们显得不专业。
我最初进行了一项看似合理的对比:Next.js(当前需要框架时的默认选择)与SolidStart及SvelteKit(听闻口碑不错的替代方案)。本以为三者对比应当简单明了,但当我构建首批实现方案并测量打包大小时,却发现了显著差异。Next.js的压缩包大小在154至176kB之间,而SolidStart和SvelteKit仅需30至54kB。这让我思考:差异源于具体框架的实现差异,还是整个框架家族的系统性特征?如果React、Angular和Vue都采用相似的架构设计,它们的打包大小是否也会呈现相似规律?为求证此点,我决定扩大评估范围。
这个问题改变了研究范围。若要为团队提出切实可行的建议,我必须测试所有主流元框架,全面了解替代方案的全貌。框架数量从三个扩展到十个。这项最初为工作需求而进行的实用性评估,逐渐演变为更宏大的探索:对2025年移动网页性能实际可行方案的半全面考察。
若您对框架多样性为何重要的理论意义感兴趣,我曾在《React 默认胜出》一文中探讨过。本文则聚焦于数据分析。
这篇文章分享了我用全部十种框架开发看板应用后的发现。两端极值分别是Marko——其主页原始包大小为12.4kB(压缩后6.8kB),以及Next.js——其主页原始包大小高达486.1kB(压缩后150.9kB)。首页原始文件大小相差达39倍。看板页面方面,Marko提供88.8kB原始文件(压缩后28.8 kB),而Next.js则为563.7kB原始文件(压缩后176.1kB),压缩后文件大小相差6.11倍。这些差异在移动网络环境下将转化为实际的加载秒数。
代码可在此处找到.
移动网页性能为何至关重要
本次评估中,移动端性能是首要限制因素。我们的用户是实地工作的房地产经纪人。他们需要我们的技术在开放看房时(30人同时挤压同一基站)、看房间隙的停车场等非WiFi办公环境下稳定运行。经纪人需要的是即时响应的工具,而非"迟迟加载"的系统。
我所在的公司没有资源开发原生应用。我们选择基于网页构建系统,这意味着只要有网址,用户就能在手机上访问。对我们的用户而言,手机端的使用频率可能与桌面端相当。
这一现实决定了评估标准。我不能仅选择"支持移动端"的框架,必须确保其在蜂窝网络环境下真正高效运行。框架体积30kB与170kB的差异绝非理论问题——这直接决定了应用呈现专业水准,还是让用户在客户面前难堪。
网站性能缓慢的商业代价:SpeedCurve的塔米·埃弗茨研究揭示了一个惊人事实。网站停机导致9%的用户永久流失,而性能缓慢则造成28%的永久流失——影响程度超过三倍。事实上,性能下降的发生频率是停机的十倍,尽管每小时成本较低,但造成的总收入损失却约为停机的两倍。除了用户流失数据,性能迟缓还会引发心理效应——用户会开始对整个品牌产生负面认知。内容显得"乏味",设计看起来"俗气",即便这些元素根本未曾改变。迟缓如毒液般侵蚀着一切。
实际成本:在3G网络环境下(1.6Mbps速率,150ms往返时延),147kB的差异意味着下载时间增加约1s,加上在移动CPU上进行解析和执行的500毫秒至1秒延迟。总计:不同框架间存在1.5至2s的性能差距。即便3G网络逐步淘汰,我们服务的房产中介仍常遭遇3G级别的网速体验。开放看房时的拥挤人流、看房间隙的停车场、信号覆盖薄弱区域(不同运营商存在差异)都会导致4G网络不稳定,10Mbps的网速可能降至1至2Mbps。在拥堵的4G环境下,147kB的数据包差异仍会造成1s以上的延迟。
“但这有缓存啊!”这种反对意见忽视了现实。缓存刷新是标准操作。每次部署都意味着用户需要重新下载。第一印象很重要,第二、第三乃至第十印象同样重要。用户对负面体验的记忆远比正面体验深刻得多。
正因如此,我将评估范围扩展至最初的三个框架之外。我需要全面了解所有选项。当用户在看房间隙于停车场打开应用时,每一秒都至关重要。优先优化移动端性能意味着桌面端在WiFi环境下默认表现优异,反之则不然。若优先优化桌面端,移动端用户体验将受损。
我发现不同框架本质上体现了截然不同的工程优先级:部分框架侧重运行时灵活性,提供丰富的抽象层以支持广泛场景;另一些则从底层设计就优先考虑运行时体积与移动端性能。我测得的房源详情页打包体积差异高达6.1倍(压缩后从28.8KB到176.1KB不等),这种差异在移动网络环境下影响极其显著。
关键要点(简而言之)
所有测试框架均实现即时首次内容绘制:现代框架在35-71毫秒区间内展现出卓越的首次内容绘制性能,使初始页面加载体验普遍达到瞬时效果。真正的差异在于包体大小:框架压缩后体积从28.8 kB(Marko)到176.1 kB(Next.js)不等,6.1倍的差距将通过增加数据消耗、延长解析时间及每次访问更高的电池消耗,对移动端用户造成影响。
包体积冠军:Marko**为主页提供88.8kB原始文件(压缩后28.8kB),比Next.js的563.7kB原始文件(压缩后176.1kB)小6.11倍。该数据比次近竞争者(SolidStart压缩后41.5kB)小31%,当包体积是绝对首要考量时,Marko无疑是最佳选择。
可恢复模式:Marko与Qwik City**均通过可恢复性技术消除了传统加载过程。Marko借助构建时分析实现最小化资源包(压缩后28.8kB),而Qwik(压缩后58.4kB)采用渐进式加载的延迟可恢复机制。两者均能在无需客户端重新执行组件的情况下实现即时交互。
Nuxt证明成熟框架仍具竞争力:原始大小224.9kB(压缩后74.7kB),首次内容加载时间38ms,Nuxt证明只要配置得当,主流三大框架也能实现新一代性能表现。Vue的架构在保持成熟生态系统的同时,实现了极具竞争力的移动网页性能。而React和Angular目前尚无途径达到类似效果。
关键缩放差异:MPA框架(Marko、HTMX)每页仅加载最小化JavaScript,功能扩展时仍保持精简。SPA框架则预先加载路由和框架运行时,即使采用代码拆分技术,基础体积仍较高。Marko无论路由总量如何,原始体积约为12.4至88.8千字节。SPA框架则维持83.9至563.7千字节的基础体积,外加路由分块。
主流框架的打包体积差异显著。TanStack Start(基于React)采用React 19实现373.6kB原始体积(压缩后118.2kB),仅比Next.js的563.7kB原始体积(压缩后176.1kB)小1.49倍。Angular通过Analog实现了具有竞争力的打包效果:原始大小376.3 kB(压缩后103.9 kB),与TanStack Start处于同等水平且领先于Next.js。Vue(通过Nuxt实现)表现更佳,其打包大小仅为224.9 kB(压缩后74.7 kB),已达到新一代框架的水准。
与此同时,SolidStart等新一代框架提供的原始包大小为128.6kB(压缩后41.5kB),比Next.js小4.24倍,比TanStack Start with React小2.85倍。完美对照组对比:TanStack Start with React(原始包373.6kB)与TanStack Start with Solid(原始包182.6kB)。相同元框架,相同模式,但 React 打包体积是 Solid 的两倍,由此可孤立 React 的运行时开销。
移动端即网络。这些数据至关重要,因为移动网络已成为数十亿人的主要上网渠道。若您的应用可通过网址访问,用户便会通过手机移动网络使用它。仅优化桌面端而寄希望于移动端勉强可用,实属本末倒置。网络即移动端。请基于这一现实进行开发。
每个构建版本均采用相同的数据库、功能和用户界面,确保对比公平性。相较于Next.js,现代替代方案的板页面包体积缩减幅度达4.24至6.11倍。重要提示:这些测量数据基于严格的基准实现方案,仅包含最小依赖项。实际生产环境中的应用通常会额外加载5至10倍的JavaScript代码(源自分析工具、身份验证系统、功能开关及第三方库),这意味着框架差异在实际应用中将产生显著累积效应。在移动设备使用蜂窝网络时,此差异影响尤为显著。
包大小的现实检验
React(通过Next.js)压缩后大小为150.9至176.1kB(原始大小486.1至563.7kB)。Angular(通过Analog)在两个页面中压缩后为103.9kB(原始大小376.3kB),其打包体积具有竞争力,与TanStack Start处于同等水平且领先于Next.js,但仍重于新一代框架。Vue(通过Nuxt)则与二者截然不同。Nuxt以74.7kB压缩包(原始224.9kB)展现更具竞争力的打包体积,成为三大元框架中唯一能在移动端网页打包体积上抗衡的方案。React需通过架构改造才能达到类似效果。Angular(通过Analog实现)虽有改进但仍重于新一代替代方案。Nuxt证明:经合理优化后,成熟框架同样能实现极具竞争力的打包体积。
React的明确策略:移动端采用React Native。React在网页端显得笨重,其架构选择是经过深思熟虑的,解决了桌面端开发中的实际问题。但对于移动网页,React的立场是:请改用React Native。其权衡在于,React Native将开发者推向应用商店——平台持有者从中抽取高达30%的交易分成,并掌控分发渠道。
其他框架的设计理念在于,只要开发者保持严谨,就能打造出卓越的移动端体验。Marko、Solid、Svelte、Qwik和Vue背后的团队,都构建了将网页作为移动端首要平台进行优化的解决方案。
大尺寸组合(从小到大)
| 框架 | 大页面原始(压缩) | 首页原始(压缩) | 与Next.js不同(大页面大小) |
|---|---|---|---|
| Marko | 88.8 kB (28.8 kB) | 12.4 kB (6.8 kB) | 小6.11倍 |
| Qwik City | 114.8 kB (58.4 kB) | 86.5 kB (42.5 kB) | 小3.02倍 |
| SvelteKit | 125.2 kB (54.1 kB)) | 103.4 kB (47.8 kB) | 小3.26倍 |
| Astro + HTMX | 127.3 kB (34.3 kB) | 86.9 kB (21.5 kB) | 小5.13倍 |
| SolidStart | 128.6 kB (41.5 kB) | 83.9 kB (29.8 kB) | 小4.24倍 |
| TanStack Start + Solid | 182.6 kB (60.4 kB) | 149.4 kB (50.8 kB) | 小2.92倍 |
| Nuxt | 224.9 kB (74.7 kB) | 224.9 kB (74.7 kB) | 小2.36倍 |
| TanStack Start | 373.6 kB (118.2 kB) | 309.4 kB (98.3 kB) | 小1.49倍 |
| Analog | 376.3 kB (103.9 kB) | 376.3 kB (103.9 kB) | 小1.70倍 |
| Next.js 16 | 563.7 kB (176.1 kB) | 486.1 kB (150.9 kB) | 基线 |
性能背景:所有测试框架均获得卓越的Lighthouse评分(100分),首次内容绘制时间相近。由于性能基本一致,打包体积成为这些框架在移动端用户体验中的差异点。6.1倍的体积差异将显著影响数据使用量、解析时间及电池消耗。
现场数据验证:Chrome用户体验报告(CrUX)提供了数百万实际网站在移动设备上使用这些框架的核心网络指标真实数据。这些现场数据补充了本文中受控环境下的测量结果。重要说明:CrUX数据反映的是普通开发者在生产环境中的实际使用情况,而非最优实现方案。若某框架在CrUX表现欠佳但在本文测试中表现良好,则说明通过合理配置、性能调优和严格管理依赖项可实现更佳效果。现场数据与优化实现之间的差距,揭示了现实使用场景中存在改进空间。
Marko框架原始文件88.8KB(压缩后28.8KB)与Next.js原始文件563.7KB(压缩后176.1KB)的差异,在移动网络环境下约转化为1.5秒的加载时差。这些秒数构成基准线——每增加一项功能或依赖项,等待加载的时间就会相应延长。
关于HTMX的重要背景:Astro + HTMX通过以客户端响应性换取服务器驱动交互,实现了最简代码库的小巧体积。对于需要丰富客户端状态的应用,Marko、Solid和Svelte在保持精简的同时提供了完整的响应性支持。
实验装置
在深入探讨前,请谨记我的渐进式复杂度宣言:本文对比的框架均属于第5级复杂度。当您需要统一的客户端状态、高度响应性及/或客户端导航时,它们是强大的工具。但多数应用在较低复杂度层级便能高效运行。例如,第三层级(通过HTMX增强的服务器渲染HTML配合基础JavaScript,如本仓库中的kanban-htmx应用所示)仅需极少JavaScript即可处理复杂交互应用。第四层级则通过Lit实现可复用Web组件。这些简化方案往往能生成更小包体积和更简洁的代码库。本文聚焦于第五层级方案,仅适用于有特殊需求的场景,同时谨记更简单的路径通常已足够。
我构建了看板应用程序十次,分别在以下框架中各实现一次: Next.js 16(基于内置编译器的React 19)展现了React虚拟DOM的自动优化特性;TanStack Start(同样基于React 19)实现了精简版React元框架,避免了应用路由器的冗余开销;TanStack Start + Solid(SolidJS 1.9)在相同元框架基础上实现了精细化响应机制; Nuxt 4(Vue 3)—— 基于Vue响应式引用,提供SSR优先开发体验;Analog(Angular 20)—— 采用Angular现代信号API及元框架工具链; Marko(@marko/run)支持流式SSR与精细化响应;SolidStart(SolidJS 1.9)通过信号实现原生Solid集成与精细化响应;SvelteKit(Svelte 5)采用符文实现精细化响应;Qwik City提供可恢复性替代水化机制;Astro + HTMX则采用传统MPA方案。
每个实现都包含完全相同的功能:看板创建与列表页面、每个看板固定四个列表(待办事项、进行中、 质量保证、已完成),卡片完整CRUD操作,列表内拖拽排序及跨列表移动,从静态用户列表分配负责人,标签管理,带作者追踪的卡片评论,完成状态切换,拖拽与图表变化的乐观UI更新(HTMX除外),以及基于Valibot的服务器端表单验证。
十款应用均基于相同架构:采用SQLite数据库配合Drizzle ORM,所有实现均使用统一模式;样式通过Tailwind CSS与DaisyUI保持界面一致性;每个框架实现包含约17个组件。最关键的是,所有应用均针对关系型数据(看板→列表→卡片→标签/评论/用户)执行真实数据库查询,而非处理硬编码数组。
您可以在这里查看代码。
关于依赖项的关键抉择:相较于多数开发者惯用的做法,这些应用刻意将依赖项降至最低。对于移动网页应用而言,每个依赖项都意味着向用户额外推送数千字节的数据。我仅使用必要的UI库(如拖放组件——不同生态系统有所差异),但刻意避开了数据获取库、状态管理辅助工具及其他框架原生已支持的实用工具。每个生态系统都有广受欢迎的便捷组件,但它们会增加包体积(React开发者常使用tanstack-query进行数据获取,或采用状态管理库及表单辅助工具)。为说明这种权衡:仅tanstack-query压缩后就重达约13KB。单此一项依赖已超过Marko整个主页包的6.8KB。通过规避这些"锦上添花"的依赖,转而使用各框架的内置功能,最终呈现的包体积差异将真实反映框架架构选择,而非功能或第三方辅助工具的数量差异。
测量方法论:所有包大小均代表使用Chrome Lighthouse测量的生产构建产物。我同时报告原始(未压缩)JavaScript大小和压缩传输大小。原始大小反映每个框架生成的实际代码量,由于不受服务器压缩设置影响,更适合用于比较。压缩大小则显示用户实际通过网络下载的数据量。所有实现均采用相同的功能、数据库和UI框架,以确保公平比较。详情请参阅完整的测量方法论。
REACT 实际应用中的天花板(TANSTACK 与 NEXT 对比)
TanStack Start实现压缩包大小为98.3至118.2kB(原始大小309.4至373.6kB),而Next.js压缩包大小为150.9至176.1kB(原始大小486.1至563.7kB)。两者均采用 React 19 版本。这仅带来 33% 至 35% 的性能提升,主要反映 App Router + RSC 的开销。
Next.js 包含完整的 React 服务器组件运行时及序列化层、组件边界管理、缓存基础设施、具备完整路由功能的应用路由器、服务器操作的渐进增强、图像优化以及中间件。而 TanStack Start 则精简了大部分功能:采用传统 SSR 方案(不含 RSC)、精简的路由系统以及简单的 RPC 风格服务器函数。
两者均采用服务器端渲染,但Next.js的RSC模型增加了显著开销。服务器组件仅在服务器端渲染,客户端组件需标记use client指令,服务器将所有内容序列化为特殊格式,客户端则需运行时代码进行反序列化并协调边界。TanStack Start采用更简洁的传统SSR方案:服务器端渲染HTML,客户端完成所有内容的动态加载。无需序列化,无需边界协调。
本次测量中,Next.js的App Router + RSC方案压缩后增加约53至58KB。剩余的98.3至118.2KB压缩数据(原始数据309.4至373.6KB)属于React核心运行时开销,主要涉及状态同步、事件系统及数据注入机制。
TanStack Start with Solid 证明了这一点:使用相同的元框架,以 Solid 替代 React 后,原始文件大小为 182.6 kB(压缩后 60.4 kB),比 TanStack Start with React 小 49%。虽然比SolidStart的128.6 kB原始大小(压缩后41.5 kB)大42%(因TanStack Router功能更丰富),但仍远优于任何React方案。
对比React基准与其他框架: Marko压缩后大小为6.8至28.8 kB(原始大小12.4至88.8 kB),比TanStack React版小4.1倍。SolidStart采用JSX时压缩后大小为29.8至41.5 kB(原始大小83.9至128.6 kB),小2.85至3.30倍。SvelteKit压缩后为47.8至54.1kB(原始大小103.4至125.2kB),体积缩减2.06至2.18倍。Qwik压缩后大小为42.5至58.4 kB(原始大小86.5至114.8 kB),体积缩小2.02至2.31倍。
React的架构(不仅是虚拟DOM,还包括合成事件、平台修补以及纯粹的功能复杂性)带来了无法避免的开销,任何元框架优化都无法消除。虚拟DOM的实现可以很小(参见仅4KB的Preact)。React 的体量反映了其刻意规避平台限制并提供丰富功能的设计选择。要突破这一上限并实现 3 至 4 倍的包体缩减,需要根本不同的架构思路。那些顺应平台而非规避平台的框架,能够实现显著的体量压缩。React 团队选择承担这些成本以解决其他问题(服务器组件、统一模式),这是合理选择。但在 React 框架内,这并非可协商的选项。
回应常见批评
我知道你们中有些人会想:"把MPA和SPA拿来比较是不是不公平?"还有"这个应用够复杂吗?"
应用复杂度辩护:这可不是什么玩具待办清单。它是一款中度复杂的应用,具备真实的数据库持久化功能(使用SQLite+Drizzle ORM),支持跨看板/列表/卡片/标签/评论的关系查询,支持拖拽排序,(部分)乐观更新,模态窗口,以及服务器端验证。它完全符合团队日常开发的内部工具或MVP产品的规格。功能包差异完全源于框架开销而非功能本身,且随着路由和依赖关系的增加,这种差距只会随着规模扩大而扩大。如果你的生产应用加入身份验证或实时功能,框架基准成本只会进一步膨胀,而非缩减。
MPA与SPA的微妙差异:路由模式之争偏离了重点,响应模型才是关键所在。借助视图过渡API和推测规则API等特性,Marko或HTMX这类MPA在导航体验上与SPA同样流畅。真正的分水岭在于扩展性。MPA每页仅需加载极少JS(例如Marko仅需6.8至28.8KB),而SPA则需拖拽83.9至563.7KB的基础运行时加载量,外加动态加载的代码块。
生态系统注记:所谓"小生态"的担忧往往被夸大。对于移动优先的应用,我们应极其审慎地选择每个依赖项——每个包都会增加打包体积和维护负担。现代AI工具如Claude、ChatGPT和Cursor擅长为特定场景生成精简代码。与其为三个功能导入50KB库,不如借助AI以2KB代码精准实现需求。这种方法能缩减包体积、提升代码可理解性并降低供应链风险。庞大生态系统虽有时有利,但当每次导入都消耗移动用户资源时,它便成了负担。
最终结论:我的推荐
在完成十个实现版本(参见下方鸣谢名单,感谢协助改进代码的热心人士)并收集所有测量数据后,结果为我们的移动优先需求提供了明确方向:
所有框架均能实现即时初始加载。关键差异在于包体积:两端极值存在6.1倍差距(压缩后28.8 kB至176.1 kB),这将通过数据成本、解析时间和电池消耗影响移动用户。请根据包体积优先级和开发者体验进行选择。
但需注意具体情况:并非所有项目都能或都应更换框架。
Next.js仍具价值的情形:对于大型现有React代码库,迁移成本可能超过性能收益。若您受限于React无法迁移,建议选择TanStack Start替代Next.js,可实现33-35%的代码包减量,且无需应对App Router的复杂性。但对于全新项目,既无历史遗留代码需维护,也无需权衡迁移成本。选择在每次访问都让用户多消耗2-3倍JavaScript的框架上构建,等同于主动接受更差的性能——尤其当更优方案无需额外成本时。"我们只懂React"并非技术限制,而是学习投入的决策。而"组织政治"虽真实存在,却不能成为技术依据,它本质上是承认存在更优方案却无法选择的现实。
常见异议的现实检验:
“但招聘呢!” 优秀的开发者会学习框架。这些替代方案其实比React更容易上手:没有钩子规则,没有依赖数组,也不需要手动实现备忘录技巧。真正的难点不在于学习曲线,而在于打造一种工程文化——这种文化既能认清限制条件,又能基于这些限制做出有意识的决策。
“但生态系统!” React的生态系统既是优势也是负担。庞大的库会提供你永远用不到的功能代码。那个支持所有语言环境的日期选择器?你只需要3个功能,却要打包300个功能。对于注重每千字节的移动优先项目,这成了问题。现代AI工具让精准构建所需功能成为可能:生成所需函数,而非为三个功能导入50KB代码。更小的包体,更清晰的代码。
"但这很冒险!" 向移动用户推送三倍大的包体才是真正风险。加载缓慢会损害品牌形象并降低转化率,所谓"安全选择"实则存在可量化的代价。
“但我的用户只用桌面端!” 说实话,“只用桌面端”通常只是逃避性能优化的借口。而且这种情况很少能持续太久。半年后有人问“我能在手机上查看吗?”,你就会突然陷入困境。不如从一开始就做好设计。桌面用户同样能受益于更快的解析和执行速度。即便在WiFi环境下,29.8KB压缩文件的加载速度也明显快于176.1KB压缩文件。更重要的是,当更优方案无需额外成本时,为何要主动接受三倍的性能损失?性能本身就是一项功能特性,与屏幕尺寸无关。在约束条件下开发能让你成为更优秀的工程师。"仅限桌面端"不应等同于"毫无纪律性"。
为何应认真考虑替代方案:新一代框架默认即具备卓越性能。它们的打包体积缩减2至6倍,优化工作量大幅降低。您将减少代码编写量、缩减JavaScript部署规模,并减少框架怪癖的调试工作。最重要的是,全新项目理应基于性能优劣而非默认选项做出选择。
这些替代方案对移动优先应用尤为重要——包体积直接影响用户体验。依赖蜂窝网络连接的移动从业者(如房产经纪人、现场服务人员、医疗工作者、配送司机和销售代表)将获益最多。构建单一高性能Web应用替代独立的Web/iOS/Android代码库,意味着更精简的团队、大幅降低的开发成本以及更快的迭代周期。
在替代方案中进行选择(按主要使用场景分类):
最小化打包:若追求极致打包体积(压缩后6.8至28.8 kB),Marko当属不二之选。当打包体积是首要考量时,Marko表现尤为突出。其MPA架构确保每页仅加载最小化JavaScript,随着路由增加仍保持精简。一旦适应其流式模型,开发体验将极佳。若偏好HTML优先的开发模式,Marko是唯一选择(尽管SvelteKit表现接近)。注:Marko 6 当前处于测试阶段(npm 仓库标记为 next),预计年底前将正式发布。此版本不计划变更 API,但将持续修复漏洞并优化性能。
JSX 熟悉度:若需从 React 迁移的最简路径,请选择 SolidStart。SolidStart 采用 JSX 语法并具备自动依赖追踪功能,既免除手动备忘操作,又能让 React 开发者即刻上手。其思维模型实际上比 React 更简洁,因为信号机制比钩子更直观。
最佳全能开发者体验:选择 SvelteKit,享受亲和力强的语法和出色的默认设置。原始大小仅 125.2kB(压缩后 54.1kB),SvelteKit 的打包体积比 Next.js 小3.26倍,默认支持渐进增强且框架开销极低。基于编译器的设计减少了运行时代码量,使组件逻辑更简洁。SvelteKit专注于纯JS、CSS和HTML的开发模式,最适合任何背景的开发者追求可读性强且框架特性少的代码。
可恢复模式:若需消除传统加载开销,请选择Marko或Qwik City。两者均避免在客户端重新执行组件,但采用不同实现方式。Marko(压缩后6.8至28.8 kB)通过构建时分析实现最小化打包,仅打包事件和特效所需代码,不支持延迟加载。Qwik City(压缩后42.5至58.4 kB)采用延迟可恢复机制,根据实际交互逐步加载JavaScript。若追求绝对最小包体积,请选择Marko;若应用程序具有大量客户端功能且能从渐进式加载中获益,则推荐Qwik。
成熟生态系统:若需Vue的成熟生态与卓越移动网页性能,Nuxt是理想之选。原始文件大小仅224.9 kB(压缩后74.7 kB),Nuxt证明成熟的"三大框架"经合理配置可实现新一代性能表现。最适合已熟悉Vue的团队、需要丰富社区包支持的项目,或重视成熟框架稳定性的团队。Nuxt完美衔接熟悉感与高性能之间的鸿沟。
正如我在《渐进式复杂性宣言》中所阐述的,这些第五级框架仅在需要统一的客户端状态和复杂响应机制时才必不可少。大多数应用程序在较低级别使用更简单的工具(如HTMX和原生JS/TS)就能蓬勃发展。
当开发者拥有真正的选择时,各方皆受益。若非SolidStart和Svelte证明了自动优化的重要性,React也不会着手添加编译器。当我们不再将"足够好"视为上限时,整个生态系统便会得到提升。
我对团队的建议:基于本次评估,Marko、SolidStart和SvelteKit都是满足我们移动端需求的优秀选择。关键在于优先级取舍:追求绝对最小包体积(Marko)、最简易的React迁移(SolidStart),还是最佳的全方位开发体验(SvelteKit)。若团队具备Vue经验,Nuxt凭借成熟的生态系统和卓越性能同样极具吸引力。
至于工作之外的个人项目,我将优先选用SvelteKit,并逐步增加Marko的使用。它们的开发体验恰到好处,代码流畅自然,让构建过程充满乐趣。
开发者体验:更简洁的思维模型
除了包体积之外,这些替代方案通常具有更简单的思维模型。React的钩子需要手动编写依赖数组,一旦出错就会导致难以调试的陈旧闭包。Solid、Svelte和Marko则采用自动依赖追踪机制。Vue需要通过.value访问实现响应式特性。Angular则带来了依赖注入的复杂性。更简单的思维模型与更小的包体积相关联,因为运行时复杂度降低意味着需要分发的代码更少。
网络是最后的公共领域:为何其重要性超越框架范畴
当你选择将原生应用提交至App Store或Google Play而非开发网页应用时,这不仅是技术层面的抉择。你实际上接受了一项二十年前难以想象的交易条款:苹果和谷歌从每笔交易中抽取高达30%的分成(具体比例因项目和类别存在例外)。它们制定规则,决定你能发布什么内容,甚至可能在次日撤销你的应用权限而你无处申诉。你别无选择。甚至无法通过价格竞争,因为这笔费用早已嵌入多数交易环节。
经济学家亚尼斯·瓦鲁法基斯在其同名著作中称之为"技术封建主义"。应用商店并非市场,而是封建领地。开发者沦为数字农奴,被捆绑在云端领主的土地(即平台)上无法脱身。用户同样被牢牢禁锢。应用商店如同精心打理的花园,由两家公司的算法主宰着你的视野。你的数据被收割,你的选择被过滤。你并非拥有选择权的顾客,而是围墙花园里的臣民。
网络则不同。没有单一公司抽成,没有算法筛选你的选择,分发是直接的。用户可以真正用脚投票。它并不完美,但这是我们所剩无几最接近开放市场的存在——开发者保有自主权,用户保有选择权。
当企业放弃网络转而只做应用时,他们并非在做中立的技术抉择。他们主动将用户从竞争激烈的市场推入封建体系。是的,这听起来很夸张,但瓦鲁法基斯多年来记录的数字平台经济模式,恰恰印证了这种动态的形成。
无论你信奉什么,你都该关注的原因: 若你倾向资本主义,应用商店营造的环境恰恰背离了资本主义的本质。垄断性租金榨取取代了竞争与创新,缺乏市场机制制衡。这并非资本主义,纯粹是榨取。
若你持反资本主义立场,技术封建主义或许比传统资本主义更恶劣——至少后者存在摩擦与监管手段,而前者两者皆无。这是完全的私有控制,毫无市场竞争可言。
无论如何,网络仍是经济活动能摆脱科技寡头掌控的最后阵地。构建网络应用至关重要,而交付轻量、快速、高效的网络应用更为关键——尤其当多数流量来自移动端时。每节省的千字节数据,都将成为团队选择网络应用而非受应用商店管控与收费的原生应用的理由。
结论:本次评估揭示了什么
原本只是为即将开展的工作项目进行的简单框架对比,却意外揭示了更深层的洞见。数据清晰表明:当框架从设计之初就优先考虑移动网页性能时,其潜力何其巨大。
本次评估揭示了重新思考基础架构带来的变革。SolidStart、SvelteKit、Qwik和Marko代表着不同的架构优先级,它们以主流框架无法企及的方式突破边界。竞争推动创新。这些替代方案证明:当移动网页性能成为首要设计约束而非事后补救时,技术突破便触手可及。
对于服务于移动网络专业人士的团队(如我们),每次访问都需为此付出代价。React和Angular常受限于架构性能天花板,而Vue证明了成熟框架经合理配置仍具竞争力。需注意的是,这些数据仅反映初始页面加载表现:MPA框架在全路由中保持轻量特性,而SPA框架则在基准上叠加路由分块负载。
对于任何启动新项目的人来说,这项评估提出了一个关键问题:是否有必要让应用程序比实际需要的重量增加6.1倍?(这还是在未计入身份验证、分析工具和第三方库的情况下——这些组件通常会使生产包体积扩大5到10倍,导致实际差距更大。)只要在初期做出正确的架构决策,打造一款在移动端运行流畅的应用并不困难。前期正确选择意味着应用能在任何场景下流畅运行,而不仅限于桌面WiFi环境。选用MPA框架可实现单页最小化打包,或采用轻量级SPA框架在熟悉模式下获得卓越性能。
若想打造超越竞争对手的产品,为何要如法炮制? 当所有人都在使用Next.js时,要赢得性能优势就意味着要逆流而上对抗React的设计。而选择Marko、SolidStart、SvelteKit或Nuxt时,优势便唾手可得:应用默认更快,无需优化即可减小包体,用户无需额外操作就能获得更佳体验,这才是真正的差异化竞争。
当你选择Marko并发布28.8KB的代码而非176.1KB的Next.js时,用户在移动网络上的体验将得到显著提升。这使得网络世界更具竞争力,成为企业更具吸引力的生存空间,从而抵御住将一切推向原生应用分发的引力。
重现这些结果
本次对比测试的所有测量均遵循严格的统计方法论,旨在确保结果的可重复性和可靠性。每个框架在每页均使用Chrome Lighthouse进行10次测量,采用移动设备模拟环境(Pixel 5,4G限速,1x CPU)。测量前通过服务器预热请求使性能趋于稳定。通过四分位距(IQR)异常值剔除法确保统计结果的稳健性。每次运行间清除浏览器缓存,以模拟首次访问场景的冷启动性能。报告中采用中位数值降低异常值影响,标准差则量化测量可靠性。完整方法论(含统计方法、测试环境细节、压缩检测机制、已知限制及可复现性指南)详见METHODOLOGY.md文档。
行动号召
亲自尝试:克隆代码库,构建全部十个实现方案,并在Chrome开发者工具中通过限速的3G网络进行测试。当移动网页成为唯一选择时,数据会清晰地说明问题。
轻松一刻:您可浏览全部十款应用,观察代码结构并感受各框架特色。我提倡为乐趣而编程,仓库中的代码或许正是尝试新事物的绝佳起点。
分享体验:你是否尝试过Marko、SolidStart、SvelteKit、Qwik或Nuxt?若要开发移动优先项目,你会选择哪个框架?欢迎在Twitter或Bluesky分享见解。
持续探索:完整指标数据及测量方法论已开源至仓库,供你验证、复现或扩展。构建自己的对比方案并分享发现成果吧。
当您使用Marko、SolidStart或SvelteKit启动新项目时,您将更快交付更精简的成果,同时减少框架开销,从而获得真正的竞争优势。
鸣谢
衷心感谢所有参与本次评估的人员。
早期草稿审阅者:Alex Russell 和 Dylan Piercey 对文章结构与论点提供了宝贵建议。
框架专项评审:
- Marko:Dylan Piercey审阅实现方案
- Qwik:Wout Mertens 审阅 Qwik 实现方案
- Analog:Brandon Roberts 和 Matthieu Riegler 提供评审与改进建议
- Solid/SolidStart:Martin Rapp、Ryan Carniato 和 Atila Fassina 提供协助
- Next.js:Sunny_man审阅Next代码
- Svelte/SvelteKit:Svelte Discord频道的热心人士,特别感谢Kevin Åberg Kultalahti、Simon H和Ben McCann
- TanStack:Manuel Schiller和Brenley Dueck协助TanStack应用开发
你们的贡献使本文更精准全面。衷心感谢!