请求
服务端代码可以读取当前请求、设置 cookie、跳转,并在不同的处理函数之间共享数据。
load、actions、API 路由和服务端元素中都可以使用这些 API。
请求钩子
src/app.server.ts 可以导出 handle,它在每个服务端请求之前执行:页面、__data.json、
表单提交、服务端元素和 API 路由。
// src/app.server.ts
import type { RequestEvent } from '@mantou/gemkit';
declare module '@mantou/gemkit' {
interface Locals {
user?: User;
}
}
export async function handle(event: RequestEvent) {
if (!event.path.startsWith('/admin')) return;
event.locals.user = await getUser(event.cookies.get('token'));
if (!event.locals.user) redirect(302, '/login');
}| 字段 | 说明 |
|---|---|
url |
页面的 URL,包含语言前缀。 |
path |
不包含语言前缀的页面路径,和路由匹配的路径一致。 |
request |
当前的 Request,预渲染时不可用。 |
cookies |
请求的 cookie,预渲染时不可用。 |
locals |
同一个请求中,和 load、actions、API 路由、服务端元素共享的数据。 |
按路径检查时使用 path,不要使用 url.pathname。__data.json 和服务端元素的请求也使用页面 URL。
locals 是一个空接口,使用 declare module 扩展类型。它属于单个请求,可以安全地存放用户数据。
- 权限检查放在
handle中,不要放在布局load中。布局load不会在表单提交和服务端元素中执行, 而且在__data.json中页面load和它并行执行,即使布局跳转也不会阻止页面load。 - 预渲染时
handle也会执行。在其中读取request或cookies、跳转或者抛出错误会让页面不被预渲染。 只对需要这些功能的路径读取它们,预渲染的页面是公开的。 - 没有服务端模块的页面在客户端导航时不会发送请求,
handle不会执行。 首次加载时页面数据已经输出到文档中,客户端导航时使用本地数据渲染。
getRequestEvent
getRequestEvent() 返回当前的 { url, path, request, cookies, locals }。它属于当前请求,
在服务端请求之外调用会抛出错误。服务端元素等没有参数的服务端代码可以使用它:
const { locals } = getRequestEvent();错误和跳转
error(status, message?) 抛出错误,渲染notFound() 等同于 error(404, 'Not Found')。在 load 中出错时,错误页面渲染在出错的页面或者布局的位置,
外层布局保留。
redirect(status, location) 抛出并响应跳转:
redirect(302, '/login');location 是包含语言前缀的完整路径。服务端响应对应的状态码和 Location 头。
客户端导航时数据文件中包含跳转地址,Gemkit 会导航到该地址。预渲染的跳转写成
<meta http-equiv="refresh"> 页面,所以静态托管也可以使用。
不是由 error() 抛出的意外错误在服务端交给 handleError:
// src/app.server.ts
export function handleError(error: unknown, event: RequestEvent) {
reportError(error, event.url);
}默认使用 console.error。错误页面显示状态码 500,生产环境中的信息是 Internal Error。
预渲染时出现意外错误会让构建失败,避免发布错误的页面。
Cookie
import type { ServerLoadContext } from '@mantou/gemkit';
export const prerender = false;
export function load({ cookies }: ServerLoadContext) {
const theme = cookies.get('theme');
cookies.set('theme', 'dark', { maxAge: 60 * 60 * 24 * 365 });
return { theme };
}cookies.set(name, value, options) 和 cookies.delete(name, options) 会在响应中添加 Set-Cookie。
默认是 Path=/; HttpOnly; SameSite=Lax,HTTPS 时 Secure 为 true,maxAge 的单位是秒。
同一个请求中,之前 set 的值可以通过 get 读取。
响应文档开始流式输出之后设置的 cookie(例如在 @server() 方法中)会被忽略。
应该在 handle、load 或者 actions 中设置。
读取 request 或 cookies,或者设置 cookie 的响应使用 Cache-Control: private, no-store,
CDN 不会在用户之间共享它们。
预渲染
预渲染时没有请求。页面或者布局读取请求、cookie 时,需要在服务端模块中导出 prerender = false:
// src/pages/account.server.ts
export const prerender = false;在布局中设置时,对它下面的所有页面生效。
