mcpField
S
sveltekit-advanced

sveltekit-advanced

github.com/full-stack-skills开发473 次安装5 周前更新
代码仓库

关于 sveltekit-advanced

sveltekit-advanced 是面向 SvelteKit 开发者的进阶功能参考技能,涵盖服务端与客户端状态、远程函数、钩子、环境变量、错误处理及路由状态管理。

主要功能

  1. 01服务端与客户端状态指导
  2. 02远程函数 API 参考
  3. 03环境变量与钩子配置
  4. 04错误处理模式
  5. 05Service Worker 与服务端专用模块
  6. 06快照与浅层路由

适用场景

  1. 01选择应用状态的存放位置
  2. 02构建类型安全的客户端/服务端调用
  3. 03配置请求钩子和错误响应
  4. 04防止浏览器端导入机密内容

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/full-stack-skills/svelte-skills --skill sveltekit-advanced

安装后在 Claude Code 中输入/sveltekit-advanced确认已加载。

包含的文件

除 SKILL.md 外,安装时一起下载的参考资料和脚本。

agents/
openai.yaml
examples/
app-modules.md
env-vars.md
errors.md
hooks.md
link-options.md
README.md
remote-functions.md
service-worker.md
shallow-snapshots.md
state-management.md
references/
app-modules.md
env-vars.md
errors.md
hooks.md
link-options.md
README.md
remote-functions.md
server-only.md
service-worker.md
shallow-snapshots.md
state-management.md

详细介绍

SvelteKit 进阶

SvelteKit 进阶功能参考。涵盖服务器端与客户端之间的状态管理、远程函数 API、环境变量(旧版和显式配置)、钩子(服务器端/共享/通用)、错误处理、链接选项、服务工作线程、仅限服务器端的模块、快照、浅层路由,以及 $app/* 模块。

来源:SvelteKit 官方 llms.txt 文档。

何时使用此技能

在以下情况下使用此技能:

  • 选择状态的存放位置(服务器上下文、URL、快照、存储)。
  • 使用 query/form/command/prerender 构建类型安全的客户端/服务器 RPC。
  • 安全读取环境变量(私有与公开、静态与动态)。
  • 通过钩子(handle、handleFetch、handleError、handleValidationError、reroute、transport、init)自定义请求处理。
  • 抛出预期/非预期错误、自定义备用错误页面,并通过 App.Error 定义错误结构的类型。
  • 使用 data-sveltekit-* 属性配置链接行为。
  • 添加服务工作线程,以支持离线使用/预缓存。
  • 通过 .server.* 或 $lib/server/ 防止机密泄露。
  • 使用快照持久化临时 DOM 状态,或通过浅层路由持久化路由历史条目。
  • 使用 $app/* 模块(forms、navigation、state、paths、server、environment、types)。

不要将此技能用于路由、表单操作(旧版)、加载、基础设置、环境变量之外的适配器配置,或 CSS/样式设置。

关键部分

1. 状态管理
  • 不要共享服务器状态 — 模块级变量(let user;)会在请求之间泄露。通过 Cookie 进行身份验证,并将数据持久化到数据库。
  • 保持 load 函数纯粹 — 不要产生副作用(例如使用全局存储)。应改为返回数据。
  • 使用上下文保存每个请求的状态 — setContext('user', () => data.user)(传入函数,使响应性能够跨越边界)。在 SSR 期间于子组件中读取上下文时,更新不会传递到父组件(父组件已完成渲染)。
  • 组件状态会在导航过程中保留 — 从 data 派生的 const 只会计算一次。对于应在数据变化时重新计算的值,请使用 $derived(...)。
  • URL 状态 — 使用搜索参数保存筛选条件/排序方式;重新加载后仍会保留,并影响 SSR。
  • 快照 — 用于可丢弃的 UI 状态(例如“手风琴面板是否展开?”),并与历史记录条目绑定。
2. 远程函数(自 2.27 起,实验性功能)

在 svelte.config.js 中启用:

kit: { experimental: { remoteFunctions: true } },
compilerOptions: { experimental: { async: true } }

从 *.remote.js 导出的类型:

类型用途主要功能
query读取动态服务器数据去重、refresh()、loading/error/current
query.batch在一次调用中批量执行 n+1 个查询返回 (input, idx) => Output
query.live实时异步可迭代对象connected、reconnect();第一个值会序列化以用于 SSR
form渐进增强的 <form><form {...createPost}>、createPost.fields.x.as('text')、validate()、enhance()、for(id)、preflight(schema)
command在事件处理器中执行命令式变更渲染期间不可调用
prerender构建时数据inputs、dynamic: true
  • 使用任何 Standard Schema(Zod/Valibot)进行验证。
  • 参数/返回值通过 devalue 序列化。
  • 在远程函数中可通过 getRequestEvent() 使用 Cookie。
  • query/form/prerender 中允许使用 redirect(...),command 中不允许。
  • 单航班变更:在服务器处理器中使用 getPosts().refresh() 或 getPost(id).set(...);客户端请求的刷新可使用 requested(getPosts, 1).refreshAll()(限制用于防范 DoS)。
3. 环境变量

旧版 $env/*(SvelteKit 2.63 之前的默认方式):

模块作用范围时机
$env/dynamic/private仅限服务端运行时(类似 process.env)
$env/dynamic/public公开(PUBLIC_*)运行时
$env/static/private仅限服务端构建时(内联)
$env/static/public公开构建时(内联)

显式环境变量(在 v3 中选择启用,且为默认方式):

在 svelte.config.js 中启用:kit.experimental.explicitEnvironmentVariables = true。然后创建 src/env.ts:

import { defineEnvVars } from '@sveltejs/kit/hooks';
import * as v from 'valibot';
import { building } from '$app/env';

export const variables = defineEnvVars({
  API_KEY: {},                              // private
  GOOGLE_ANALYTICS_ID: { public: true },    // public
  SHOW_DEBUG_OVERLAY: { public: true, static: true },  // inlined, dead-code-eliminated
  SECRET: { schema: building ? v.optional(v.string()) : v.string() },
  CACHE_TTL_SECONDS: { description: 'How long...' }
});

从 $app/env/private 或 $app/env/public 导入。$app/environment 已重命名为 $app/env。

4. 钩子

三个可选文件:src/hooks.server.js、src/hooks.client.js、src/hooks.js。

服务端(hooks.server.js):

  • handle({ event, resolve }) — 在每次请求时运行;返回 Response,或调用 resolve(event, opts)。resolve 的选项:transformPageChunk、filterSerializedResponseHeaders、preload。有多个时使用 sequence(...)。
  • handleFetch({ request, fetch, event }) — 将跨源请求重写为内部 API 请求;为同级子域转发 cookie。
  • handleValidationError({ event, issues }) — 为有误的远程函数参数自定义 400 响应。

共享(hooks.server.js 和 hooks.client.js):

  • handleError({ error, event, status, message }) — 仅用于意外错误。返回 { message, ... } -> 成为 page.error。绝不能抛出异常。服务端类型:HandleServerError;客户端类型:HandleClientError;客户端的 event 是 NavigationEvent。
  • init() — 在启动时运行一次;适用于建立数据库连接。

通用(hooks.js):

  • reroute({ url, fetch }) — 将 URL 转换为不同的路由(例如,i18n)。必须是纯函数且幂等。自 2.18 起可以是异步函数。
  • transport — 为跨越服务端/客户端边界的类型(例如,Vector)自定义编码器/解码器。
5. 错误
  • 预期错误 — 从 @sveltejs/kit 调用 error(404, 'Not found')(或 error(404, { message, code }))。渲染最近的 +error.svelte,并设置状态码。page.error = 传入的对象。
  • 意外错误 — 任何其他异常。不会对外公开(显示通用的 Internal Error);通过 handleError 路由处理。
  • 渲染错误 — 通过 experimental.handleRenderingErrors 选择启用。错误会直接作为 error 属性传递给 +error.svelte(而非通过 page.error)。
  • 响应 — 使用自定义 src/error.html,其中包含 %sveltekit.status% 和 %sveltekit.error.message%。根目录 +layout.server.js 中的错误会使用回退页面(根目录包含 +error.svelte)。
  • 类型安全 — 在 src/app.d.ts 中声明 App.Error 接口:
declare global {
  namespace App {
    interface Error { message: string; code: string; id: string; }
  }
}
6. 链接选项

在 <a>(或其父元素)上使用 data-sveltekit-* 属性。也可用于 <form method="GET">。

属性值效果
preload-datahover(默认)、tap在悬停/轻触时预加载 load 数据
preload-codeeager、viewport、hover、tap仅预加载路由代码
reload布尔值强制整页导航(rel="external" 也会如此)
replacestate布尔值替换历史记录条目,而非推入新条目
keepfocus布尔值导航后保持焦点在同一元素上
noscroll布尔值禁用导航后滚动到顶部

在子树中使用 data-sveltekit-preload-data="false" 可禁用预加载。遵循 navigator.connection.saveData 的设置。

7. Service Worker

放置 src/service-worker.js(或 src/service-worker/index.js)——会自动打包并注册。通过配置禁用后,可手动注册。

可从 $service-worker 获取:base、build、files、prerendered、version。

标准做法:在安装时缓存 build + files,获取时优先使用网络,缓存作为回退。跳过带有 Cache-Control: no-store 的响应(实时查询)。在开发环境中,build/prerendered 是空数组。

8. 仅限服务端的模块
  • $env/static/private 和 $env/dynamic/private — 仅限服务端。
  • $app/server — 仅限服务端。
  • 你的模块 — 添加 .server.js 后缀,或放在 $lib/server/ 下。

从浏览器代码中非法导入会导致构建报错。对于仅用于类型的导入,请使用 import type。在测试中会禁用检测(process.env.TEST === 'true')。

9. 快照与浅层路由

快照 — 从 +page.svelte 或 +layout.svelte 导出 snapshot = { capture, restore }。页面更新前会将快照保存到 sessionStorage;浏览历史导航时会恢复。内容必须可序列化为 JSON。不要返回过大的对象。

浅层路由 — pushState(url, state) / replaceState(url, state) 会创建历史记录条目,但不会进行导航。通过 page.state 读取。使用 preloadData(href) 获取 load 数据,然后使用 pushState(href, { selected: result.data }),即可在模态框中渲染另一个 +page.svelte。首次 SSR 和首次绘制期间,page.state 始终为 {}。

快速修复

症状修复方法
用户数据在请求之间泄漏不要使用模块级变量;使用 Cookie + DB
导航时 load 数据未更新对从 data 派生的值使用 $derived(...),而不是 const
Cannot import $lib/server/...将共享类型移到 import type
实时查询流停止使用 .reconnect() 重新连接;不要在 SW 中缓存 no-store 响应
error(404, ...) 显示空白页在离路由最近的位置添加 +error.svelte
仅限服务端的环境变量泄漏到客户端使用 $env/static/private 或 .server 命名
验证失败时显示通用的 400 消息实现 handleValidationError
导航时组件状态丢失使用 {#key page.url.pathname}<X/>{/key} 包裹,以强制重新挂载

注意事项

  • load 必须是纯函数 — 不要写入全局 store。应改为返回数据。
  • SSR 期间的上下文更新不会向上传播 — 向下传递状态,避免水合时出现闪烁。
  • query.batch 会返回单个函数,用于将各个输入映射到输出;它不会直接返回结果数组。
  • SSR 上的 query.live 只返回第一个生成的值,然后关闭。
  • 渲染期间不能调用 command — 应从事件处理器中调用。
  • requested 需要 limit — 用于防止 DoS;只有在明确安全时才传入 Infinity。
  • SvelteKit 2.x 中,error() 不再需要 throw。
  • SSR 和首次绘制时,page.state 为 {} — 不要依赖它进行关键渲染。
  • reroute 必须是纯函数且幂等 — 其结果会按 URL 在客户端缓存。
  • 开发模式下,Service Worker 的 build / prerendered 为空 — 请在生产构建中测试。
  • 向同级子域名转发 Cookie 需要手动实现 handleFetch — SvelteKit 无法判断哪个父域 Cookie 属于哪个子域名。
  • handleError 不得抛出异常 — 使用 try/catch 包裹有风险的操作。

常见问题

问:$app/state 和 $app/stores 有什么区别? 答:$app/state(自 2.12 起)基于 rune,具有响应性。$app/stores 是基于 store 的旧版本。使用 Svelte 5 时,请使用 $app/state。

问:query 和 prerender 有什么区别? 答:query 用于动态数据;prerender 用于构建时冻结的数据,这些数据可以从 CDN 提供。完全预渲染的页面不能使用 query。

问:form 和 command 有什么区别? 答:form 支持渐进增强——无需 JS 即可使用,并可应用于 <form>。command 仅限 JS,通过事件处理程序调用。优先使用 form。

问:$env/dynamic 和 $env/static 有什么区别? 答:dynamic 在运行时读取(例如 process.env);static 在构建时内联(可启用死代码消除)。对于构建时已知的值,请使用 static。

问:$env/static/private 和 $env/dynamic/private 有什么区别? 答:两者的访问限制相同;区别在于读取值的时机。Static 支持 DCE;dynamic 允许在运行时覆盖(例如 MY_FLAG=1 npm run dev)。

问:可以在 +page.svelte 中使用 $lib/server 模块吗? 答:不可以——仅限服务器端的模块不能被客户端代码直接或间接导入。SvelteKit 会在构建时报错。

问:提交后如何让焦点保持在搜索输入框中? 答:将 data-sveltekit-keepfocus 添加到 <form>。

问:如何在 load 中抛出 404? 答:import { error } from '@sveltejs/kit'; error(404, 'Not found');(在 SvelteKit 2 中不要使用 throw)。

问:应该使用 Sentry 吗? 答:应该——在 hooks.server.js 和 hooks.client.js 的 handleError 中进行初始化。服务器端使用 HandleServerError;客户端使用带有 NavigationEvent 的 HandleClientError。

示例

主题文件
使用 context + URL + derived 管理状态examples/state-management.md
Remote query/form/command/batch/liveexamples/remote-functions.md
环境变量(旧版 + 显式配置)examples/env-vars.md
服务器端 + 通用 hooksexamples/hooks.md
预期/意外错误 + App.Errorexamples/errors.md
data-sveltekit-* 链接选项examples/link-options.md
Service worker 预缓存 + 离线examples/service-worker.md
$app/* 模块(表单、导航、状态、路径、服务器)examples/app-modules.md
Snapshots + 浅层路由examples/shallow-snapshots.md

参考资料

主题文件
状态管理references/state-management.md
Remote 函数references/remote-functions.md
环境变量references/env-vars.md
Hooksreferences/hooks.md
错误references/errors.md
链接选项references/link-options.md
Service workerreferences/service-worker.md
仅限服务器端的模块references/server-only.md
$app/* 模块references/app-modules.md
Snapshots 和浅层路由references/shallow-snapshots.md

评论

支持 Markdown