QWIK DOCS / V2

心智模型

用 JavaScript streaming 理解 Qwik:为什么首屏可交互时间可以是一个常量。

约 4 分钟Qwik v203 / 19
本页目录5 节
  1. 水合到底在做什么
  2. Qwik 的选择:暂停与续接
  3. 五个机制一起工作
  4. 为什么 TTI 可以接近 O(1)
  5. 这意味着什么

如果你用过 React、Vue、Svelte 或 Solid,组件、响应式和 JSX 都不陌生。Qwik 的不同之处在于它如何把 JavaScript 送到浏览器:不是先全部下载再执行,而是像视频一样边播边缓冲。

视频不必等整部下载完才能播放。用户可以立即开始,也可以跳到任意位置;已经缓冲的部分立即响应,没有缓冲的部分稍微等一会儿。JavaScript streaming 做的是同一件事,只不过它优化的是「不执行代码」。

01水合到底在做什么#

常规 SSR 框架会先生成 HTML,然后在浏览器里重新执行组件模板,重建组件树、找到事件监听器、恢复状态。这一步叫水合(hydration)。页面看起来已经完成,实际上框架还在后台重放服务端做过的工作。

  • 监听器:重新找到 DOM 节点并绑定事件。
  • 组件树:重新执行模板,建立组件边界与更新关系。
  • 状态:把服务端取到的数据重新放回 store。

水合的成本有两层:下载当前页面的全部组件代码,以及执行这些代码。应用越大,首屏可交互时间(TTI)越接近线性增长。

02Qwik 的选择:暂停与续接#

Qwik 在服务端渲染完成后不销毁现场。组件边界、事件引用、状态和订阅关系被序列化进 HTML。浏览器不需要重建这些信息,而是在用户第一次交互时,恢复对应的一小部分执行环境。

常规 SSR + 水合Qwik
首屏HTML 可用,但需等待 JS 才能交互HTML 可用,交互在第一次操作时续接
启动成本随页面代码量增长与首个交互所需的符号相关
事件代码随组件一起下载交互时才下载
组件树浏览器重新执行模板重建从 HTML 中恢复

03五个机制一起工作#

  1. 细粒度响应式(signals):状态变化只更新订阅它的 DOM,不需要重渲染整棵子树。
  2. 自动代码拆分(Optimizer):按 $ 抽取符号,构建期生成可以在运行时独立加载的 chunk。
  3. 状态序列化(resumability):把状态、监听器、组件边界和订阅图写进 HTML。
  4. 即时事件注册(Qwikloader):一段很小的内联脚本先接管用户事件,此时应用代码还不需要存在。
  5. 缓冲预加载(Preloader):页面 load 之后空闲预取最可能用到的符号,交互发生时优先插队加载。

这五个机制缺一不可。没有信号,单个交互会迫使整棵子树重新渲染;没有 Optimizer,代码无法被拆成可独立加载的符号;没有序列化,浏览器就必须重放。

04为什么 TTI 可以接近 O(1)#

在 Qwik 中,页面加载后并不需要执行所有组件。用户点击按钮时,Qwikloader 已经记录了这个事件;Qwik 解析 HTML 中的引用,下载事件处理函数及其依赖,然后执行。其他组件的代码可以继续躺在缓存里。

因此 TTI 不取决于页面有多少功能,而取决于首个交互需要多少代码。一个包含上百个组件的页面,也可以用很小的启动成本变得可交互。

05这意味着什么#

  • 可扩展:功能增加不必以首屏变慢为代价,团队不需要为了性能停止加功能。
  • 开发者省心:懒加载边界由构建器生成,不需要手工规划 import()。
  • 用户更快:弱网与低端设备上,首屏可交互时间更稳定。

接下来读可恢复性,看 Qwik 具体把哪些信息写进了 HTML。