一个框架为了“不水合”,把HTML注释都删了

2026年10月1日,UTC时间下午3点49分,Qwik 2.0 RC发布到了npm。不到7个小时之内,SvelteKit 3和Remix 3.0.0也相继发布。三个主流框架在同一天撞车,像一场没有预谋的集体换血。

但Qwik 2.0 RC的发布说明里,最值得读的不是新功能。它讲的是一个框架为了守住"可恢复性(Resumability)"这条底线,愿意放弃什么 。答案之一是:HTML注释。

一、先说清楚:Qwik的"可恢复性"到底在反对什么

大多数框架的SSR流程是这样的:服务端生成HTML,浏览器收到后,把同一套组件代码再加载一遍、执行一遍 ,重新挂载事件监听器、重建组件树和状态。这个过程叫 hydration(水合) 。

问题在于:应用越大,启动时必须执行的JavaScript就越多。首屏可交互时间不是由"页面多大"决定的,而是由"你的组件代码总量"决定的。

Qwik不做这件事。它的官方文档把执行描述为:在服务器上"暂停",在浏览器中"恢复" 。监听器直接写进HTML属性,比如 on:click="./chunk.js#handler";组件边界、应用状态、状态与组件之间的订阅关系,全部序列化进HTML。浏览器里最先运行的只有一小段叫Qwikloader的脚本,它挂一个全局监听器,等用户真正点击某个元素时,才根据属性去加载对应的chunk。

首屏JavaScript的成本,被设计成与组件数量无关。 这是Qwik最核心、也最不容妥协的承诺。

二、v1的代价:那些"可爱的小注释",其实很重

"把状态和边界序列化进HTML"这件事,在Qwik v1里靠的是一个不太起眼的载体:HTML注释。

v1的HTML长这样(简化示例):

html 复制代码
<main>
  <!--qv q:id=7 q:key=counter-->
  Count: <!--t=8-->123<!---->!
  <button on:click="...">+1</button>
  <!--/qv-->
</main>

<!--qv--> 标记组件边界,<!--t=8--> 标记某个文本节点由哪个signal驱动更新。

Qwik 2.0的RC公告把这些注释称为"cute little comments",但同一份公告非常直白地列出了它们的代价:

  • 需要单次有序遍历才能写出;
  • 给CPU和内存带来负担;
  • 让响应式更新比平均水平的框架更慢;
  • 让乱序流式传输变得不可能;
  • 缓慢的获取会阻塞它下面的所有内容。

最后两条是致命的。2026年的Web平台正在全力推进"内容就绪就交付"的流式渲染,而Qwik v1的注释标记机制,在物理上要求HTML必须按顺序、一次性完整地写出来。这跟它自己想讲的故事------让浏览器"少做额外工作"------在深层逻辑上是矛盾的。

三、v2的答案:把"携带标记的载体"直接扔掉

Qwik 2.0的选择是:不再用HTML注释来携带这些信息。

v2的HTML变成了这样:

html 复制代码
<main>
  Count: 123!
  <button on:click="...">+1</button>
</main>
<script type="qwik/state">[...]</script>
<script type="qwik/vnode">...</script>

body里的注释从60个降到了0 。所有边界、状态、文本更新位置的信息,被压缩进了HTML末尾的两个script块:qwik/state 和 qwik/vnode。

这不是简单的"挪了个位置"。它带来的是一连串结构性的解放:

  • 乱序流式传输成为可能(实验性):页面不必等最慢的那块数据就绪才能开始输出。
  • 更新不再需要重新解析HTML:vnode在内存中作为轻量对象存在,signal变化时直接更新对应的文本节点或属性,不再走"重新读HTML找标记"的路径。
  • 长任务可以被切片:调度器每15毫秒把控制权交还给浏览器,点击和输入在长渲染期间不会被阻塞。

v2还沿用了2024年"Towards Qwik 2.0"设计文章中预告的一系列"抠细节"决策:vnode信息编码成约9个字符的字符串,元素引用用深度优先序号代替ID属性,vnode按需生成、用数组而非对象存储以帮助JIT优化。

所有这些决策指向同一个目标:不让浏览器做额外的工作。

四、牺牲了什么?社区并不全是掌声

Qwik 2.0 RC不是一次"纯升级"。它有一个社区已经注意到的代价:打包体积增加了。虽然"加载前运行的JS"从59KB降到了9KB,但整体的bundle size是上升的。

这是一个值得认真对待的权衡。Qwik v1的注释标记虽然"重",但它让框架在运行时需要的额外数据结构更少。v2把信息集中到末尾的script块,让流式传输和更新效率获得了结构性提升,代价是一次性传输的字节数变多了。

Qwik团队的选择隐含了一个判断:对于"可恢复性"这个目标来说,"首屏运行多少JS"比"总共下载多少字节"更重要。用户感知到的"卡",往往来自主线程被JavaScript执行阻塞,而不是来自多下载了几KB。v2把成本从"运行时"挪到了"传输时",同时换来了流式传输和可切片的长任务。

这个判断是否正确,取决于你的用户场景。对于网络极差、但设备性能尚可的环境,bundle增大可能是一个真实的代价。Qwik 2.0不是免费的午餐,它是一次有明确方向的取舍。

五、同一天发布,三种不同的"框架减法"

Qwik 2.0 RC的发布日,恰好撞上了SvelteKit 3和Remix 3.0.0。三个框架在同一天做出了三个方向不同的"减法":

Qwik 2.0做的是"移除运行时标记" 。它删掉HTML注释,把状态和vnode集中到末尾,目标是让"恢复"这件事在流式和调度层面都变得更干净。

Remix 3做的是"移除框架依赖" 。它不再绑定React,变成一个基于Web primitives(Request/Response)的单一包,把"全栈框架"和"UI库"解耦。

SvelteKit 3做的是"移除运行时本身" 。编译时框架的路线走到极致,运行时尽可能小,逻辑尽可能前移到编译阶段。

三个框架在同一天交出了三种不同的答案,但它们问的是同一个问题:在2026年,"框架"到底应该在运行时承担多少重量?

六、这对前端开发者意味着什么?

第一,框架的"设计哲学"正在变成可量化的工程取舍。 Qwik为了"可恢复性"删掉HTML注释,付出bundle增大的代价。这不是抽象的理念之争,而是"首屏运行JS"和"总传输字节"之间的具体权衡。当你评估一个框架时,看它愿意为什么付出代价,比看它宣传什么更重要。

第二,流式渲染正在从"框架特性"变成"平台预期"。 Chrome的声明式部分更新和Qwik 2.0的乱序流式实验指向同一个方向:HTML不应该因为交付顺序而被惩罚。当平台层开始解决这个问题时,框架在流式上的"独家能力"会逐渐被标准化。

第三,"不水合"的路线仍然小众,但它的压力正在倒逼整个生态思考启动成本。 Qwik不是主流选择。但它用两年零八个月打磨v2、为了一个目标删掉自己最显眼的机制,这件事本身在提醒所有人:首屏可交互时间不应该随着应用变大而无限增长。

写在最后

2026年10月1日,Qwik 2.0 RC发布。同一天,SvelteKit 3和Remix 3.0.0也来了。

Qwik 2.0最值得读的部分,不是它新增了什么,而是它愿意删除什么。HTML注释从60个降到0,bundle变大了,但乱序流式传输和15毫秒调度变成了可能。

一个框架为了守住"不水合"这条线,把自己最显眼的机制都扔掉了。这种级别的取舍,比任何 benchmark 数字都更能说明一个框架到底相信什么。

参考链接:

相关推荐
计算机魔术师2 小时前
AI渗透框架3小时破云,中国黑客组织正在升级打法
前端
蒲公英内测分发2 小时前
智能手环出海测试,海外合作方分散在不同国家,Android 测试包怎么持续分发和更新?
android·前端·人工智能·测试工具·智能手表
朱涛的自习室2 小时前
高价软件已死,我让 AI 开启了「平替计划」(Day 7 / 7)
android·前端·github
沙蒿同学2 小时前
Wails v3 实战:一个桌面提醒客户端,从 v2 升到 v3 的全过程
前端·后端·github
inquisiter3 小时前
KernelGpt的部分尝试
java·前端·apache
the局外人3 小时前
用 TRAE 把 Markdown文档 搬到微信公众号
前端
Autumn_ing3 小时前
AI原型设计工具怎么选?可编辑原型与可运行前端适合什么场景
前端·小程序·产品经理·代码·codex·墨刀ai客户端·ai原型
夕阳_醉了3 小时前
前端通用组件开发全指南|从 0 到 1 打造稳定可复用的业务组件
前端
Amos_Web4 小时前
Rspack 源码解析(三十):SourceMapDevToolPlugin 如何生成并关联 source map
前端