QWIK DOCS / V2

服务端函数

用 server$ 把任意函数变成类型安全的 RPC,同时保留 RequestEvent。

约 2 分钟Qwik v214 / 19
本页目录3 节
  1. 在服务端拿到请求上下文
  2. 可取消的调用
  3. 什么该放在服务端

server$() 把一个函数变成客户端可调用的 RPC。调用方拿到的仍是普通异步函数,但函数体只在服务器上执行,参数与返回值经过 Qwik 序列化。

tsxsrc/routes/contact/index.tsx
import { component$, useSignal } from '@qwik.dev/core';
import { server$ } from '@qwik.dev/router';

export const sendMessage = server$(async function (name: string) {
  await mailer.send({
    to: 'hello@example.com',
    subject: `来自 ${name} 的消息`,
  });
  return { ok: true };
});

export default component$(() => {
  const name = useSignal('');
  const status = useSignal('');

  return (
    <form
      preventdefault:submit
      onSubmit$={async () => {
        const res = await sendMessage(name.value);
        status.value = res.ok ? '已发送' : '失败';
      }}
    >
      <input bind:value={name} />
      <button type="submit">发送</button>
      <p>{status.value}</p>
    </form>
  );
});

参数可以是原始值、对象、数组、Date、Map、Set、Promise 以及可序列化的 QRL。不能传类实例、函数或流;需要传 DOM 引用时用 noSerialize() 明确标注。

01在服务端拿到请求上下文#

server$ 函数中的 this 是 RequestEvent。你可以读取 Cookie、Header、URL 与环境变量,也可以写响应 Cookie。

tsxcode
export const whoami = server$(function () {
  const session = this.cookie.get('session')?.value;
  const token = this.env.get('API_TOKEN');
  return {
    session: session ?? null,
    authorized: Boolean(session && token),
  };
});

02可取消的调用#

当调用方传入 AbortSignal 时,server$ 函数会把它作为第一个参数注入。连接断开后你可以提前终止长任务。

tsxcode
export const search = server$(async function (
  signal: AbortSignal,
  query: string
) {
  const res = await fetch(
    `https://api.example.com/search?q=${encodeURIComponent(query)}`,
    { signal }
  );
  return res.json();
});

// 调用
const controller = new AbortController();
const result = await search(controller.signal, 'qwik');

03什么该放在服务端#

需求首选
页面渲染前需要数据routeLoader$
表单写操作routeAction$
按钮触发的任意服务端逻辑server$
对外提供 REST / Webhookindex.ts 端点
数据库、密钥、第三方 SDK.server.ts 模块

文件名包含 .server. 或位于 src/**/server/** 的模块只允许服务端代码导入。客户端若误引,构建会直接失败,而不是把密钥悄悄打进 bundle。

tssrc/db.server.ts
export async function findUser(id: string) {
  return db.users.find(id);
}