RESUMABLE WEB FRAMEWORKQWIK / V2.0
从服务器
继续运行。
Qwik 把状态和事件监听器写进 HTML。浏览器不需要重新执行整个应用,只加载下一次交互真正需要的代码。零成本打造即时加载的 Web 应用。
- HYDRATION
- 无
- QWIKLOADER
- ≈1 KB
- STARTUP
- O(1)
LIVE / RESUME点击左侧按钮观察
RESUME_CONSOLE / 001
服务端已暂停01 / SERVERPAUSED
component
Counter#c_01已序列化listener
on:click → s_LToOr已序列化state
{ count: 0 }已序列化没有 re-render,没有事件重绑,只有一份可读的 HTML。
02 / BROWSERWAITING
serialized-htmlSSR已送达chunk/resume.js0.9 kB待请求chunk/on-click.js0.3 kB待请求0 次重渲0/2 chunkcount = 0
SSR 输出 → 浏览器恢复 → 按需加载符号
01 / COMPONENT REPLAY0启动时不重放组件
02 / EAGER JS≈1 KBqwikloader 内联在 HTML
03 / STARTUP SCALEO(1)应用变大,启动成本不变
04 / FIRST PAINTHTML内容先到,交互随后
01 / THE COST
水合,是一次不必要的重启。
其他框架服务端渲染后,还要在浏览器里重新执行一遍组件、恢复状态、重新绑定监听器。页面看起来已经好了,主线程却还在忙。
“可恢复性不是更快的重新执行,而是根本不需要重新执行。”
传统水合HYDRATION
启动时执行全部组件与副作用,再把这些工作交给浏览器。
Qwik 恢复RESUME
读取已序列化的状态,只下载并执行被触发的那个符号。
启动时执行首次交互才加载示意图
STARTUP COST / APP SIZE示意图
02 / O(1) STARTUP
应用变大,
启动不变。
Qwik 的可恢复模型让服务端承担渲染,客户端只恢复状态。新增页面、组件和功能,不会自动变成首屏的 JavaScript 负担。
- A首屏只发送内容与序列化状态。
- B事件代码在首次触发时下载。
- C预取让首次交互通常无需等待。
03 / HOW IT WORKS
五个机制,一个结果。
不是把水合做得更快,而是把水合从架构里移除。
04 / OPTIMIZER
每个 $ 都是一个
懒加载边界。
构建期切分,运行期按需加载。你写的是普通函数,Optimizer 负责边界。
import { component$, useSignal, useTask$ } from '@qwik.dev/core';
export const Counter = component$(() => {
const count = useSignal(0);
useTask$(({ track }) => {
track(count);
console.log('count is', count.value);
});
return (
<button onClick$={() => count.value++}>
{count.value}
</button>
);
});OPTIMIZER OUTPUTwaiting
01
Counter_component.js—渲染函数
等待拆分
02
Counter_useTask.js—响应任务
等待拆分
03
Counter_onClick.js—事件处理
等待拆分
每个 $ 都是一个可独立请求的符号。Qwik 不会为了一个点击事件加载整棵组件树。
05 / ROUTER & DATA
一次请求,
一条完整的数据路径。
页面、loader、action 与端点共享同一个 RequestEvent,没有客户端与服务端两套数据逻辑。
import { component$ } from '@qwik.dev/core';
import { routeLoader$ } from '@qwik.dev/router';
export const useProducts = routeLoader$(async ({ url }) => {
const category = url.searchParams.get('category');
return db.products.list({ category });
});
export default component$(() => {
const products = useProducts();
return <ProductGrid items={products.value} />;
});loader 只在服务端执行,结果随 HTML 一起序列化。