QWIK DOCS / V2

数据加载

在服务端加载数据,返回可直接读取的 ComputedSignal。

约 4 分钟Qwik v212 / 19
本页目录3 节
  1. 三个关键性质
  2. 把 RequestEvent 当作入口
  3. 缓存与序列化

routeLoader$() 定义只在服务端执行的数据加载函数。它在 SSR 时运行一次,SPA 导航到对应路由时再次运行,返回一个 ComputedSignal,组件用 .value 读取。

tsxsrc/routes/product/[id]/index.tsx
import { component$ } from '@qwik.dev/core';
import { routeLoader$ } from '@qwik.dev/router';

export const useProduct = routeLoader$(async ({ params }) => {
  const res = await fetch(`https://api.example.com/products/${params.id}`);
  return res.json();
});

export default component$(() => {
  const product = useProduct();
  return <h1>{product.value.name}</h1>;
});

loader 必须从 index.tsx 或 layout.tsx 导出。跨路由复用时,在独立文件中定义,再从每个需要它的路由文件重新导出。

01三个关键性质#

  • 只在服务端运行:函数体不会进入客户端 bundle,数据库查询与密钥都安全。
  • 按路由缓存:同一 URL 的多次调用共享一份结果,而不是每个组件各请求一次。
  • 返回 ComputedSignal:读取 .value 得到数据;数据未就绪时读取会挂起,出错时重新抛出错误。

一个页面可以声明多个 loader,它们并行执行。声明更多 loader 本身不会拖慢渲染。

tsxcode
export const useSession = routeLoader$(({ cookie }) => {
  return { token: cookie.get('session')?.value ?? null };
});

export const useTodos = routeLoader$(async ({ sharedMap }) => {
  return db.todos.list();
});

02把 RequestEvent 当作入口#

属性用途
params动态路由参数
url完整 URL,含查询参数
cookie读取或写入 Cookie
request原始 Request 对象,可读 Header
env平台注入的环境变量
fail / error / redirect失败、抛出状态码、重定向
sharedMap在本次请求的多个处理函数间共享数据
tsxcode
export const useArticle = routeLoader$(async ({ params, fail }) => {
  const article = await db.articles.find(params.slug);
  if (!article) {
    return fail(404, { message: '文章不存在' });
  }
  return article;
});

return fail(status, data) 把失败作为数据返回,组件通过 signal.value.failed 判断;throw error(status) 则让读取 .value 时抛出错误,需要在 <Catch> 中处理。

03缓存与序列化#

Qwik Router 把每个 loader 的结果暴露为独立 JSON 端点,浏览器 HTTP 缓存是唯一的新鲜度权威。默认 no-cache:每次导航都重新验证,配合 ETag 通常只返回 304。

选项默认值作用
cacheControl'no-cache'设置 loader JSON 的 Cache-Control
eTag—命中时返回 304,跳过 loader
search[]声明依赖哪些查询参数
serializationStrategy'never'是否把数据内嵌进 HTML
blockSSRtrue是否等待 loader 完成再渲染
tsxcode
export const useCatalog = routeLoader$(
  async ({ url }) => {
    return db.products.list({
      category: url.searchParams.get('category'),
    });
  },
  {
    cacheControl: 60,
    search: ['category'],
  }
);

默认情况下 loader 数据不会写进 HTML:首屏立即返回,客户端恢复后再按需请求 JSON。如果数据很小且首屏必须可见,可设 serializationStrategy: 'always',代价是 HTML 变大。