We read every piece of feedback, and take your input very seriously.
To see all available qualifiers, see our documentation.
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Svelte,一个语法简洁、入门容易,面向未来的前端框架。
从 Svelte 诞生之初,就备受开发者的喜爱,根据统计,从 2019 年到 2024 年,连续 6 年一直是开发者最感兴趣的前端框架 No.1:
Svelte 以其独特的编译时优化机制著称,具有轻量级、高性能、易上手等特性,非常适合构建轻量级 Web 项目。
为了帮助大家学习 Svelte,我同时搭建了 Svelte 最新的中文文档站点。
如果需要进阶学习,也可以入手我的小册《Svelte 开发指南》,语法篇、实战篇、原理篇三大篇章带你系统掌握 Svelte!
欢迎围观我的“网页版朋友圈”、加入“冴羽·成长陪伴社群”,踏上“前端大佬成长之路”。
“Hooks” 是您声明的应用程序范围的函数,SvelteKit 会在响应特定事件时调用它们,让您能够对框架的行为进行更为精细的控制。
有三个 hook 文件,都是可选的:
src/hooks.server.js
src/hooks.client.js
src/hooks.js
这些模块中的代码会在应用程序启动时运行,这使得它们对初始化数据库客户端等操作很有用。
[!NOTE] 您可以通过 config.kit.files.hooks 配置这些文件的位置。
config.kit.files.hooks
以下 hook 可以添加到 src/hooks.server.js 中:
这个函数在 SvelteKit 服务端每次接收到 request 时运行 — 无论是在应用程序运行时,还是在预渲染过程中 — 并决定response。
它接收一个表示请求的 event 对象和一个名为 resolve 的函数,该函数渲染路由并生成一个 Response。这允许您修改响应头或响应体,或完全绕过 SvelteKit(例如,用于以编程方式实现路由)。
event
resolve
Response
/// file: src/hooks.server.js /** @type {import('@sveltejs/kit').Handle} */ export async function handle({ event, resolve }) { if (event.url.pathname.startsWith('/custom')) { return new Response('custom response'); } const response = await resolve(event); return response; }
[!NOTE] 对静态资源的请求 — 包括已经预渲染的页面 — 不会由 SvelteKit 处理。
如果未实现,默认为 ({ event, resolve }) => resolve(event)。
({ event, resolve }) => resolve(event)
要向请求中添加自定义数据(这些数据会传递给 +server.js 中的处理程序和服务端的 load 函数),可以填充 event.locals 对象,如下所示。
+server.js
load
event.locals
/// file: src/hooks.server.js // @filename: ambient.d.ts type User = { name: string; } declare namespace App { interface Locals { user: User; } } const getUserInformation: (cookie: string | void) => Promise<User>; // @filename: index.js // ---cut--- /** @type {import('@sveltejs/kit').Handle} */ export async function handle({ event, resolve }) { event.locals.user = await getUserInformation(event.cookies.get('sessionid')); const response = await resolve(event); response.headers.set('x-custom-header', 'potato'); return response; }
您可以定义多个 handle 函数,并使用sequence 辅助函数执行它们。
handle
sequence
resolve 还支持第二个可选参数,让您能够更好地控制响应的渲染方式。该参数是一个对象,可以包含以下字段:
transformPageChunk(opts: { html: string, done: boolean }): MaybePromise<string | undefined>
done
%sveltekit.head%
filterSerializedResponseHeaders(name: string, value: string): boolean
fetch
preload(input: { type: 'js' | 'css' | 'font' | 'asset', path: string }): boolean
<head>
+page.svelte
import './styles.css
preload
js
css
asset
/// file: src/hooks.server.js /** @type {import('@sveltejs/kit').Handle} */ export async function handle({ event, resolve }) { const response = await resolve(event, { transformPageChunk: ({ html }) => html.replace('old', 'new'), filterSerializedResponseHeaders: (name) => name.startsWith('x-'), preload: ({ type, path }) => type === 'js' || path.includes('/important/') }); return response; }
注意,resolve(...) 永远不会抛出错误,它总是会返回一个带有适当状态码的 Promise<Response>。如果在 handle 期间其他地方抛出错误,这将被视为致命错误,SvelteKit 将根据 Accept 头部返回错误的 JSON 表示或回退错误页面 — 后者可以通过 src/error.html 自定义。您可以在这里阅读更多关于错误处理的信息。
resolve(...)
Promise<Response>
Accept
src/error.html
这个函数允许您修改(或替换)在服务端上运行的 load 或 action 函数中发生的 fetch 请求(或在预渲染期间)。
action
例如,当用户执行客户端导航到相应页面时,您的 load 函数可能会向公共 URL(如 https://api.yourapp.com)发出请求,但在 SSR 期间,直接访问 API 可能更有意义(绕过位于它和公共互联网之间的代理和负载均衡器)。
https://api.yourapp.com
/// file: src/hooks.server.js /** @type {import('@sveltejs/kit').HandleFetch} */ export async function handleFetch({ request, fetch }) { if (request.url.startsWith('https://api.yourapp.com/')) { // 克隆原始请求,但改变 URL request = new Request( request.url.replace('https://api.yourapp.com/', 'http://localhost:9999/'), request ); } return fetch(request); }
认证凭据
对于同源请求,除非 credentials 选项设置为 "omit",否则 SvelteKit 的 fetch 实现会转发 cookie 和 authorization 头部。
credentials
"omit"
cookie
authorization
对于跨源请求,如果请求 URL 属于应用程序的子域,则会包含 cookie — 例如,如果您的应用程序在 my-domain.com 上,而您的 API 在 api.my-domain.com 上,cookie 将包含在请求中。
my-domain.com
api.my-domain.com
如果您的应用程序和 API 在兄弟子域上 — 例如 www.my-domain.com 和 api.my-domain.com — 那么属于共同父域(如 my-domain.com)的 cookie 将不会被包含,因为 SvelteKit 无法知道 cookie 属于哪个域。在这些情况下,您需要使用 handleFetch 手动包含 cookie:
www.my-domain.com
handleFetch
/// file: src/hooks.server.js // @errors: 2345 /** @type {import('@sveltejs/kit').HandleFetch} */ export async function handleFetch({ event, request, fetch }) { if (request.url.startsWith('https://api.my-domain.com/')) { request.headers.set('cookie', event.request.headers.get('cookie')); } return fetch(request); }
以下 hook 可以同时添加到 src/hooks.server.js 和 src/hooks.client.js 中:
如果在加载或渲染期间抛出意外错误,此函数将被调用,并传入 error、event、status 代码和 message。这允许两件事:
error
status
message
{ message }
$page.error
对于从您的代码(或您的代码调用的库代码)抛出的错误,状态将为 500,消息将为 "Internal Error"。虽然 error.message 可能包含不应暴露给用户的敏感信息,但 message 是安全的(尽管对普通用户来说没有意义)。
error.message
要以类型安全的方式向 $page.error 对象添加更多信息,您可以通过声明 App.Error 接口(必须包含 message: string,以保证合理的回退行为)来自定义预期的形状。这允许您 — 例如 — 附加一个跟踪 ID,供用户在与技术支持人员通信时引用:
App.Error
message: string
/// file: src/app.d.ts declare global { namespace App { interface Error { message: string; errorId: string; } } } export {};
/// file: src/hooks.server.js // @errors: 2322 2353 // @filename: ambient.d.ts declare module '@sentry/sveltekit' { export const init: (opts: any) => void; export const captureException: (error: any, opts: any) => void; } // @filename: index.js // ---cut--- import * as Sentry from '@sentry/sveltekit'; Sentry.init({/*...*/}) /** @type {import('@sveltejs/kit').HandleServerError} */ export async function handleError({ error, event, status, message }) { const errorId = crypto.randomUUID(); // 与 https://sentry.io/ 集成的示例 Sentry.captureException(error, { extra: { event, errorId, status } }); return { message: '哎呀!', errorId }; }
/// file: src/hooks.client.js // @errors: 2322 2353 // @filename: ambient.d.ts declare module '@sentry/sveltekit' { export const init: (opts: any) => void; export const captureException: (error: any, opts: any) => void; } // @filename: index.js // ---cut--- import * as Sentry from '@sentry/sveltekit'; Sentry.init({/*...*/}) /** @type {import('@sveltejs/kit').HandleClientError} */ export async function handleError({ error, event, status, message }) { const errorId = crypto.randomUUID(); // 与 https://sentry.io/ 集成的示例 Sentry.captureException(error, { extra: { event, errorId, status } }); return { message: '哎呀!', errorId }; }
[!NOTE] 在 src/hooks.client.js 中,handleError 的类型是 HandleClientError 而不是 HandleServerError,并且 event 是一个 NavigationEvent 而不是 RequestEvent。
handleError
HandleClientError
HandleServerError
NavigationEvent
RequestEvent
此函数不会因为预期的错误(那些使用从 @sveltejs/kit 导入的 error 函数抛出的错误)而被调用。
@sveltejs/kit
在开发过程中,如果由于 Svelte 代码中的语法错误而发生错误,传入的错误会附加一个 frame 属性,突出显示错误的位置。
frame
[!NOTE] 确保 handleError 永远不会抛出错误
这个函数在服务端创建或应用程序在浏览器中启动时运行一次,是执行异步工作(如初始化数据库连接)的有用位置。
[!NOTE] 如果您的环境支持顶级 await,init 函数实际上与在模块顶层编写初始化逻辑没有什么不同,但一些环境 — 尤其是 Safari — 不支持。
init
/// file: src/hooks.server.js import * as db from '$lib/server/database'; /** @type {import('@sveltejs/kit').ServerInit} */ export async function init() { await db.connect(); }
Note
在浏览器中,init 中的异步工作会延迟水合,所以要注意您在那里放什么。
以下 hook 可以添加到 src/hooks.js 中。通用 hook 在服务端和客户端都运行(不要与共享 hook 混淆,后者是特定环境的)。
这个函数在 handle 之前运行,允许您更改 URL 如何转换为路由。返回的路径名(默认为 url.pathname)用于选择路由及其参数。
url.pathname
例如,您可能有一个 src/routes/[[lang]]/about/+page.svelte 页面,它应该可以访问为 /en/about 或 /de/ueber-uns 或 /fr/a-propos。您可以用 reroute 来实现:
src/routes/[[lang]]/about/+page.svelte
/en/about
/de/ueber-uns
/fr/a-propos
reroute
/// file: src/hooks.js // @errors: 2345 // @errors: 2304 /** @type {Record<string, string>} */ const translated = { '/en/about': '/en/about', '/de/ueber-uns': '/de/about', '/fr/a-propos': '/fr/about' }; /** @type {import('@sveltejs/kit').Reroute} */ export function reroute({ url }) { if (url.pathname in translated) { return translated[url.pathname]; } }
lang 参数将从返回的路径名正确派生。
lang
使用 reroute 不会改变浏览器地址栏的内容,也不会改变 event.url 的值。
event.url
这是一组 传输器,允许您跨服务端/客户端边界传递自定义类型 - 从 load 和 form actions 返回的类型。每个传输器都包含一个 encode 函数,该函数对服务端上的值进行编码(或对任何不是该类型的实例返回 false),以及一个相应的 decode 函数:
encode
decode
/// file: src/hooks.js import { Vector } from '$lib/math'; /** @type {import('@sveltejs/kit').Transport} */ export const transport = { Vector: { encode: (value) => value instanceof Vector && [value.x, value.y], decode: ([x, y]) => new Vector(x, y) } };
点击查看中文文档:SvelteKit 高级路由
系统学习 Svelte,欢迎入手小册《Svelte 开发指南》。语法篇、实战篇、原理篇三大篇章带你系统掌握 Svelte!
此外我还写过 JavaScript 系列、TypeScript 系列、React 系列、Next.js 系列、冴羽答读者问等 14 个系列文章, 全系列文章目录:https://github.com/mqyqingfeng/Blog
The text was updated successfully, but these errors were encountered:
No branches or pull requests
前言
Svelte,一个语法简洁、入门容易,面向未来的前端框架。
从 Svelte 诞生之初,就备受开发者的喜爱,根据统计,从 2019 年到 2024 年,连续 6 年一直是开发者最感兴趣的前端框架 No.1:
Svelte 以其独特的编译时优化机制著称,具有轻量级、高性能、易上手等特性,非常适合构建轻量级 Web 项目。
为了帮助大家学习 Svelte,我同时搭建了 Svelte 最新的中文文档站点。
如果需要进阶学习,也可以入手我的小册《Svelte 开发指南》,语法篇、实战篇、原理篇三大篇章带你系统掌握 Svelte!
欢迎围观我的“网页版朋友圈”、加入“冴羽·成长陪伴社群”,踏上“前端大佬成长之路”。
Hooks
“Hooks” 是您声明的应用程序范围的函数,SvelteKit 会在响应特定事件时调用它们,让您能够对框架的行为进行更为精细的控制。
有三个 hook 文件,都是可选的:
src/hooks.server.js
— 您的应用程序的服务端 hooksrc/hooks.client.js
— 您的应用程序的客户端 hooksrc/hooks.js
— 您的应用程序的在客户端和服务端都运行的 hook这些模块中的代码会在应用程序启动时运行,这使得它们对初始化数据库客户端等操作很有用。
服务端 hook
以下 hook 可以添加到
src/hooks.server.js
中:handle
这个函数在 SvelteKit 服务端每次接收到 request 时运行 — 无论是在应用程序运行时,还是在预渲染过程中 — 并决定response。
它接收一个表示请求的
event
对象和一个名为resolve
的函数,该函数渲染路由并生成一个Response
。这允许您修改响应头或响应体,或完全绕过 SvelteKit(例如,用于以编程方式实现路由)。如果未实现,默认为
({ event, resolve }) => resolve(event)
。locals
要向请求中添加自定义数据(这些数据会传递给
+server.js
中的处理程序和服务端的load
函数),可以填充event.locals
对象,如下所示。您可以定义多个
handle
函数,并使用sequence
辅助函数执行它们。resolve
还支持第二个可选参数,让您能够更好地控制响应的渲染方式。该参数是一个对象,可以包含以下字段:transformPageChunk(opts: { html: string, done: boolean }): MaybePromise<string | undefined>
— 对 HTML 应用自定义转换。如果done
为 true,则是最后一个块。块不保证是格式良好的 HTML(例如,它们可能包含一个元素的开始标签但没有结束标签),但它们总是会在合理的边界处分割,比如%sveltekit.head%
或布局/页面组件。filterSerializedResponseHeaders(name: string, value: string): boolean
— 确定当load
函数使用fetch
加载资源时,哪些头部应该包含在序列化的响应中。默认情况下,不会包含任何头部。preload(input: { type: 'js' | 'css' | 'font' | 'asset', path: string }): boolean
— 确定应该在<head>
标签中添加哪些文件以预加载。该方法在构建代码块时被调用,每个找到的文件都会被调用 — 例如,如果您在+page.svelte
中有import './styles.css
,在访问该页面时,preload
将传入该 CSS 文件的解析路径进行调用。注意,在开发模式下不会调用preload
,因为它依赖于构建时的分析。预加载可以通过更早下载资源来提高性能,但如果不必要地下载太多内容也会适得其反。默认情况下,会预加载js
和css
文件。目前不会预加载asset
文件,但我们可能会在评估反馈后添加此功能。注意,
resolve(...)
永远不会抛出错误,它总是会返回一个带有适当状态码的Promise<Response>
。如果在handle
期间其他地方抛出错误,这将被视为致命错误,SvelteKit 将根据Accept
头部返回错误的 JSON 表示或回退错误页面 — 后者可以通过src/error.html
自定义。您可以在这里阅读更多关于错误处理的信息。handleFetch
这个函数允许您修改(或替换)在服务端上运行的
load
或action
函数中发生的fetch
请求(或在预渲染期间)。例如,当用户执行客户端导航到相应页面时,您的
load
函数可能会向公共 URL(如https://api.yourapp.com
)发出请求,但在 SSR 期间,直接访问 API 可能更有意义(绕过位于它和公共互联网之间的代理和负载均衡器)。认证凭据
对于同源请求,除非
credentials
选项设置为"omit"
,否则 SvelteKit 的fetch
实现会转发cookie
和authorization
头部。对于跨源请求,如果请求 URL 属于应用程序的子域,则会包含
cookie
— 例如,如果您的应用程序在my-domain.com
上,而您的 API 在api.my-domain.com
上,cookie 将包含在请求中。如果您的应用程序和 API 在兄弟子域上 — 例如
www.my-domain.com
和api.my-domain.com
— 那么属于共同父域(如my-domain.com
)的 cookie 将不会被包含,因为 SvelteKit 无法知道 cookie 属于哪个域。在这些情况下,您需要使用handleFetch
手动包含 cookie:共享 hook
以下 hook 可以同时添加到
src/hooks.server.js
和src/hooks.client.js
中:handleError
如果在加载或渲染期间抛出意外错误,此函数将被调用,并传入
error
、event
、status
代码和message
。这允许两件事:{ message }
)会成为$page.error
的值。对于从您的代码(或您的代码调用的库代码)抛出的错误,状态将为 500,消息将为 "Internal Error"。虽然
error.message
可能包含不应暴露给用户的敏感信息,但message
是安全的(尽管对普通用户来说没有意义)。要以类型安全的方式向
$page.error
对象添加更多信息,您可以通过声明App.Error
接口(必须包含message: string
,以保证合理的回退行为)来自定义预期的形状。这允许您 — 例如 — 附加一个跟踪 ID,供用户在与技术支持人员通信时引用:此函数不会因为预期的错误(那些使用从
@sveltejs/kit
导入的error
函数抛出的错误)而被调用。在开发过程中,如果由于 Svelte 代码中的语法错误而发生错误,传入的错误会附加一个
frame
属性,突出显示错误的位置。init
这个函数在服务端创建或应用程序在浏览器中启动时运行一次,是执行异步工作(如初始化数据库连接)的有用位置。
Note
在浏览器中,
init
中的异步工作会延迟水合,所以要注意您在那里放什么。通用 hook
以下 hook 可以添加到
src/hooks.js
中。通用 hook 在服务端和客户端都运行(不要与共享 hook 混淆,后者是特定环境的)。reroute
这个函数在
handle
之前运行,允许您更改 URL 如何转换为路由。返回的路径名(默认为url.pathname
)用于选择路由及其参数。例如,您可能有一个
src/routes/[[lang]]/about/+page.svelte
页面,它应该可以访问为/en/about
或/de/ueber-uns
或/fr/a-propos
。您可以用reroute
来实现:lang
参数将从返回的路径名正确派生。使用
reroute
不会改变浏览器地址栏的内容,也不会改变event.url
的值。传输
这是一组 传输器,允许您跨服务端/客户端边界传递自定义类型 - 从
load
和 form actions 返回的类型。每个传输器都包含一个encode
函数,该函数对服务端上的值进行编码(或对任何不是该类型的实例返回 false),以及一个相应的decode
函数:进一步阅读
Svelte 中文文档
点击查看中文文档:SvelteKit 高级路由
系统学习 Svelte,欢迎入手小册《Svelte 开发指南》。语法篇、实战篇、原理篇三大篇章带你系统掌握 Svelte!
此外我还写过 JavaScript 系列、TypeScript 系列、React 系列、Next.js 系列、冴羽答读者问等 14 个系列文章, 全系列文章目录:https://github.com/mqyqingfeng/Blog
欢迎围观我的“网页版朋友圈”、加入“冴羽·成长陪伴社群”,踏上“前端大佬成长之路”。
The text was updated successfully, but these errors were encountered: