QWIK DOCS / V2

QRL 与懒加载边界

理解可序列化的代码引用,以及 $ 到底改变了什么。

约 2 分钟Qwik v215 / 19
本页目录3 节
  1. 从 JSX 到 HTML
  2. 为什么不用 import()
  3. 写 $ 函数时的规则

QRL 是 Qwik URL 的缩写。它不是网络请求,而是一个可序列化的代码引用:指向某个 chunk 里的某个符号,必要时还携带闭包捕获的值。

textQRL 的基本形状
./chunks/counter.js#Counter_onClick[0,1]

# 之前:chunk 路径
# 之后:符号名
# 方括号:捕获变量在 q:obj 中的索引

01从 JSX 到 HTML#

tsx你写的代码
export const Counter = component$(() => {
  const count = useSignal(0);

  return (
    <button onClick$={() => count.value++}>
      {count.value}
    </button>
  );
});

Optimizer 会把组件、事件处理函数与任务拆成独立模块。每个 $ 都是切分点。服务端渲染后,HTML 中留下的是指针,而不是已经执行过的闭包。

htmlSSR 输出(简化)
<button q-e:click="./chunks/counter.js#Counter_onClick[0,1]">
  0
</button>
<script type="qwik/json">{ ... }</script>

页面加载时只执行约 1 KB 的 qwikloader。用户点击按钮,qwikloader 冒泡找到 q-e:click,解析相对路径,加载对应 chunk,调用符号,再用 useLexicalScope() 恢复捕获的 signal。

02为什么不用 import()#

问题QRL 的解法
动态 import 无法序列化到 HTMLQRL 本身就是可写进 HTML 的字符串
import 只到 chunk,不能指定符号URL 后带 #SymbolName
相对路径离开模块后失去基准用 q:base 在 DOM 中解析
闭包变量无法跨进程恢复索引引用 qwik/json 中的对象
开发者手动切分边界Optimizer 根据 $ 自动切分

03写 $ 函数时的规则#

  • 捕获的局部变量必须是 const,并且可序列化。
  • 模块级变量必须被导入或导出,Optimizer 才能在新模块里重新引用它。
  • 不要捕获类实例、DOM 节点或函数;需要跨边界时改用可序列化数据或 noSerialize()。
  • 组件、任务、事件处理器分别成为独立符号,浏览器只下载真正执行的那部分。