Hooks
“Hooks” 是您声明的应用程序范围的函数,SvelteKit 会在响应特定事件时调用它们,让您能够对框架的行为进行更为精细的控制。
有三个 hook 文件,都是可选的:
src/hooks.server.js
— 您的应用程序的服务端 hooksrc/hooks.client.js
— 您的应用程序的客户端 hooksrc/hooks.js
— 您的应用程序的在客户端和服务端都运行的 hook
这些模块中的代码会在应用程序启动时运行,这使得它们对初始化数据库客户端等操作很有用。
您可以通过
config.kit.files.hooks
配置这些文件的位置。
服务端 hook
以下 hook 可以添加到 src/hooks.server.js
中:
handle
这个函数在 SvelteKit 服务端每次接收到 request 时运行 — 无论是在应用程序运行时,还是在预渲染过程中 — 并决定response。
它接收一个表示请求的 event
对象和一个名为 resolve
的函数,该函数渲染路由并生成一个 Response
。这允许您修改响应头或响应体,或完全绕过 SvelteKit(例如,用于以编程方式实现路由)。
/** @type {import('@sveltejs/kit').Handle} */
export async function function handle({ event, resolve }: {
event: any;
resolve: any;
}): Promise<any>
handle({ event: any
event, resolve: any
resolve }) {
if (event: any
event.url.pathname.startsWith('/custom')) {
return new var Response: new (body?: BodyInit | null, init?: ResponseInit) => Response
This Fetch API interface represents the response to a request.
Response('custom response');
}
const const response: any
response = await resolve: any
resolve(event: any
event);
return const response: any
response;
}
import type { type Handle = (input: {
event: RequestEvent;
resolve(event: RequestEvent, opts?: ResolveOptions): MaybePromise<Response>;
}) => MaybePromise<...>
The handle
hook runs every time the SvelteKit server receives a request and
determines the response.
It receives an event
object representing the request and a function called resolve
, which renders the route and generates a Response
.
This allows you to modify response headers or bodies, or bypass SvelteKit entirely (for implementing routes programmatically, for example).
Handle } from '@sveltejs/kit';
export const const handle: Handle
handle: type Handle = (input: {
event: RequestEvent;
resolve(event: RequestEvent, opts?: ResolveOptions): MaybePromise<Response>;
}) => MaybePromise<...>
The handle
hook runs every time the SvelteKit server receives a request and
determines the response.
It receives an event
object representing the request and a function called resolve
, which renders the route and generates a Response
.
This allows you to modify response headers or bodies, or bypass SvelteKit entirely (for implementing routes programmatically, for example).
Handle = async ({ event: RequestEvent<Partial<Record<string, string>>, string | null>
event, resolve: (event: RequestEvent, opts?: ResolveOptions) => MaybePromise<Response>
resolve }) => {
if (event: RequestEvent<Partial<Record<string, string>>, string | null>
event.RequestEvent<Partial<Record<string, string>>, string | null>.url: URL
The requested URL.
url.URL.pathname: string
pathname.String.startsWith(searchString: string, position?: number): boolean
Returns true if the sequence of elements of searchString converted to a String is the
same as the corresponding elements of this object (converted to a String) starting at
position. Otherwise returns false.
startsWith('/custom')) {
return new var Response: new (body?: BodyInit | null, init?: ResponseInit) => Response
This Fetch API interface represents the response to a request.
Response('custom response');
}
const const response: Response
response = await resolve: (event: RequestEvent, opts?: ResolveOptions) => MaybePromise<Response>
resolve(event: RequestEvent<Partial<Record<string, string>>, string | null>
event);
return const response: Response
response;
};
对静态资源的请求 — 包括已经预渲染的页面 — 不会由 SvelteKit 处理。
如果未实现,默认为 ({ event, resolve }) => resolve(event)
。
locals
要向请求中添加自定义数据(这些数据会传递给 +server.js
中的处理程序和服务端的 load
函数),可以填充 event.locals
对象,如下所示。
/** @type {import('@sveltejs/kit').Handle} */
export async function function handle(input: {
event: RequestEvent;
resolve(event: RequestEvent, opts?: ResolveOptions): MaybePromise<Response>;
}): MaybePromise<...>
handle({ event: RequestEvent<Partial<Record<string, string>>, string | null>
event, resolve: (event: RequestEvent, opts?: ResolveOptions) => MaybePromise<Response>
resolve }) {
event: RequestEvent<Partial<Record<string, string>>, string | null>
event.RequestEvent<Partial<Record<string, string>>, string | null>.locals: App.Locals
Contains custom data that was added to the request within the server handle hook
.
locals.App.Locals.user: User
user = await const getUserInformation: (cookie: string | void) => Promise<User>
getUserInformation(event: RequestEvent<Partial<Record<string, string>>, string | null>
event.RequestEvent<Partial<Record<string, string>>, string | null>.cookies: Cookies
Get or set cookies related to the current request
cookies.Cookies.get(name: string, opts?: CookieParseOptions): string | undefined
Gets a cookie that was previously set with cookies.set
, or from the request headers.
get('sessionid'));
const const response: Response
response = await resolve: (event: RequestEvent, opts?: ResolveOptions) => MaybePromise<Response>
resolve(event: RequestEvent<Partial<Record<string, string>>, string | null>
event);
const response: Response
response.Response.headers: Headers
headers.Headers.set(name: string, value: string): void
set('x-custom-header', 'potato');
return const response: Response
response;
}
import type { type Handle = (input: {
event: RequestEvent;
resolve(event: RequestEvent, opts?: ResolveOptions): MaybePromise<Response>;
}) => MaybePromise<...>
The handle
hook runs every time the SvelteKit server receives a request and
determines the response.
It receives an event
object representing the request and a function called resolve
, which renders the route and generates a Response
.
This allows you to modify response headers or bodies, or bypass SvelteKit entirely (for implementing routes programmatically, for example).
Handle } from '@sveltejs/kit';
export const const handle: Handle
handle: type Handle = (input: {
event: RequestEvent;
resolve(event: RequestEvent, opts?: ResolveOptions): MaybePromise<Response>;
}) => MaybePromise<...>
The handle
hook runs every time the SvelteKit server receives a request and
determines the response.
It receives an event
object representing the request and a function called resolve
, which renders the route and generates a Response
.
This allows you to modify response headers or bodies, or bypass SvelteKit entirely (for implementing routes programmatically, for example).
Handle = async ({ event: RequestEvent<Partial<Record<string, string>>, string | null>
event, resolve: (event: RequestEvent, opts?: ResolveOptions) => MaybePromise<Response>
resolve }) => {
event: RequestEvent<Partial<Record<string, string>>, string | null>
event.RequestEvent<Partial<Record<string, string>>, string | null>.locals: App.Locals
Contains custom data that was added to the request within the server handle hook
.
locals.App.Locals.user: User
user = await const getUserInformation: (cookie: string | void) => Promise<User>
getUserInformation(event: RequestEvent<Partial<Record<string, string>>, string | null>
event.RequestEvent<Partial<Record<string, string>>, string | null>.cookies: Cookies
Get or set cookies related to the current request
cookies.Cookies.get(name: string, opts?: CookieParseOptions): string | undefined
Gets a cookie that was previously set with cookies.set
, or from the request headers.
get('sessionid'));
const const response: Response
response = await resolve: (event: RequestEvent, opts?: ResolveOptions) => MaybePromise<Response>
resolve(event: RequestEvent<Partial<Record<string, string>>, string | null>
event);
const response: Response
response.Response.headers: Headers
headers.Headers.set(name: string, value: string): void
set('x-custom-header', 'potato');
return const response: Response
response;
};
您可以定义多个 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
文件,但我们可能会在评估反馈后添加此功能。
/** @type {import('@sveltejs/kit').Handle} */
export async function function handle({ event, resolve }: {
event: any;
resolve: any;
}): Promise<any>
handle({ event: any
event, resolve: any
resolve }) {
const const response: any
response = await resolve: any
resolve(event: any
event, {
transformPageChunk: ({ html }: {
html: any;
}) => any
transformPageChunk: ({ html: any
html }) => html: any
html.replace('old', 'new'),
filterSerializedResponseHeaders: (name: any) => any
filterSerializedResponseHeaders: (name: any
name) => name: any
name.startsWith('x-'),
preload: ({ type, path }: {
type: any;
path: any;
}) => any
preload: ({ type: any
type, path: any
path }) => type: any
type === 'js' || path: any
path.includes('/important/')
});
return const response: any
response;
}
import type { type Handle = (input: {
event: RequestEvent;
resolve(event: RequestEvent, opts?: ResolveOptions): MaybePromise<Response>;
}) => MaybePromise<...>
The handle
hook runs every time the SvelteKit server receives a request and
determines the response.
It receives an event
object representing the request and a function called resolve
, which renders the route and generates a Response
.
This allows you to modify response headers or bodies, or bypass SvelteKit entirely (for implementing routes programmatically, for example).
Handle } from '@sveltejs/kit';
export const const handle: Handle
handle: type Handle = (input: {
event: RequestEvent;
resolve(event: RequestEvent, opts?: ResolveOptions): MaybePromise<Response>;
}) => MaybePromise<...>
The handle
hook runs every time the SvelteKit server receives a request and
determines the response.
It receives an event
object representing the request and a function called resolve
, which renders the route and generates a Response
.
This allows you to modify response headers or bodies, or bypass SvelteKit entirely (for implementing routes programmatically, for example).
Handle = async ({ event: RequestEvent<Partial<Record<string, string>>, string | null>
event, resolve: (event: RequestEvent, opts?: ResolveOptions) => MaybePromise<Response>
resolve }) => {
const const response: Response
response = await resolve: (event: RequestEvent, opts?: ResolveOptions) => MaybePromise<Response>
resolve(event: RequestEvent<Partial<Record<string, string>>, string | null>
event, {
ResolveOptions.transformPageChunk?(input: {
html: string;
done: boolean;
}): MaybePromise<string | undefined>
Applies custom transforms to HTML. If done
is true, it’s the final chunk. Chunks are not guaranteed to be well-formed HTML
(they could include an element’s opening tag but not its closing tag, for example)
but they will always be split at sensible boundaries such as %sveltekit.head%
or layout/page components.
transformPageChunk: ({ html: string
html }) => html: string
html.String.replace(searchValue: string | RegExp, replaceValue: string): string (+3 overloads)
Replaces text in a string, using a regular expression or search string.
replace('old', 'new'),
ResolveOptions.filterSerializedResponseHeaders?(name: string, value: string): boolean
Determines which headers should be included in serialized responses when a load
function loads a resource with fetch
.
By default, none will be included.
filterSerializedResponseHeaders: (name: string
name) => name: string
name.String.startsWith(searchString: string, position?: number): boolean
Returns true if the sequence of elements of searchString converted to a String is the
same as the corresponding elements of this object (converted to a String) starting at
position. Otherwise returns false.
startsWith('x-'),
ResolveOptions.preload?(input: {
type: "font" | "css" | "js" | "asset";
path: string;
}): boolean
Determines what should be added to the <head>
tag to preload it.
By default, js
and css
files will be preloaded.
preload: ({ type: "font" | "css" | "js" | "asset"
type, path: string
path }) => type: "font" | "css" | "js" | "asset"
type === 'js' || path: string
path.String.includes(searchString: string, position?: number): boolean
Returns true if searchString appears as a substring of the result of converting this
object to a String, at one or more positions that are
greater than or equal to position; otherwise, returns false.
includes('/important/')
});
return const response: Response
response;
};
注意,resolve(...)
永远不会抛出错误,它总是会返回一个带有适当状态码的 Promise<Response>
。如果在 handle
期间其他地方抛出错误,这将被视为致命错误,SvelteKit 将根据 Accept
头部返回错误的 JSON 表示或回退错误页面 — 后者可以通过 src/error.html
自定义。您可以在这里阅读更多关于错误处理的信息。
handleFetch
这个函数允许您修改(或替换)在服务端上运行的 load
或 action
函数中发生的 fetch
请求(或在预渲染期间)。
例如,当用户执行客户端导航到相应页面时,您的 load
函数可能会向公共 URL(如 https://api.yourapp.com
)发出请求,但在 SSR 期间,直接访问 API 可能更有意义(绕过位于它和公共互联网之间的代理和负载均衡器)。
/** @type {import('@sveltejs/kit').HandleFetch} */
export async function function handleFetch({ request, fetch }: {
request: any;
fetch: any;
}): Promise<any>
handleFetch({ request: any
request, fetch: any
fetch }) {
if (request: any
request.url.startsWith('https://api.yourapp.com/')) {
// 克隆原始请求,但改变 URL
request: any
request = new var Request: new (input: RequestInfo | URL, init?: RequestInit) => Request
This Fetch API interface represents a resource request.
Request(
request: any
request.url.replace('https://api.yourapp.com/', 'http://localhost:9999/'),
request: any
request
);
}
return fetch: any
fetch(request: any
request);
}
import type { type HandleFetch = (input: {
event: RequestEvent;
request: Request;
fetch: typeof fetch;
}) => MaybePromise<Response>
The handleFetch
hook allows you to modify (or replace) a fetch
request that happens inside a load
function that runs on the server (or during pre-rendering)
HandleFetch } from '@sveltejs/kit';
export const const handleFetch: HandleFetch
handleFetch: type HandleFetch = (input: {
event: RequestEvent;
request: Request;
fetch: typeof fetch;
}) => MaybePromise<Response>
The handleFetch
hook allows you to modify (or replace) a fetch
request that happens inside a load
function that runs on the server (or during pre-rendering)
HandleFetch = async ({ request: Request
request, fetch: {
(input: RequestInfo | URL, init?: RequestInit): Promise<Response>;
(input: string | URL | globalThis.Request, init?: RequestInit): Promise<Response>;
}
fetch }) => {
if (request: Request
request.Request.url: string
Returns the URL of request as a string.
url.String.startsWith(searchString: string, position?: number): boolean
Returns true if the sequence of elements of searchString converted to a String is the
same as the corresponding elements of this object (converted to a String) starting at
position. Otherwise returns false.
startsWith('https://api.yourapp.com/')) {
// 克隆原始请求,但改变 URL
request: Request
request = new var Request: new (input: RequestInfo | URL, init?: RequestInit) => Request
This Fetch API interface represents a resource request.
Request(
request: Request
request.Request.url: string
Returns the URL of request as a string.
url.String.replace(searchValue: string | RegExp, replaceValue: string): string (+3 overloads)
Replaces text in a string, using a regular expression or search string.
replace('https://api.yourapp.com/', 'http://localhost:9999/'),
request: Request
request
);
}
return fetch: (input: string | URL | globalThis.Request, init?: RequestInit) => Promise<Response> (+1 overload)
fetch(request: Request
request);
};
认证凭据
对于同源请求,除非 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:
/** @type {import('@sveltejs/kit').HandleFetch} */
export async function function handleFetch({ event, request, fetch }: {
event: any;
request: any;
fetch: any;
}): Promise<any>
handleFetch({ event: any
event, request: any
request, fetch: any
fetch }) {
if (request: any
request.url.startsWith('https://api.my-domain.com/')) {
request: any
request.headers.set('cookie', event: any
event.request.headers.get('cookie'));
}
return fetch: any
fetch(request: any
request);
}
import type { type HandleFetch = (input: {
event: RequestEvent;
request: Request;
fetch: typeof fetch;
}) => MaybePromise<Response>
The handleFetch
hook allows you to modify (or replace) a fetch
request that happens inside a load
function that runs on the server (or during pre-rendering)
HandleFetch } from '@sveltejs/kit';
export const const handleFetch: HandleFetch
handleFetch: type HandleFetch = (input: {
event: RequestEvent;
request: Request;
fetch: typeof fetch;
}) => MaybePromise<Response>
The handleFetch
hook allows you to modify (or replace) a fetch
request that happens inside a load
function that runs on the server (or during pre-rendering)
HandleFetch = async ({ event: RequestEvent<Partial<Record<string, string>>, string | null>
event, request: Request
request, fetch: {
(input: RequestInfo | URL, init?: RequestInit): Promise<Response>;
(input: string | URL | globalThis.Request, init?: RequestInit): Promise<Response>;
}
fetch }) => {
if (request: Request
request.Request.url: string
Returns the URL of request as a string.
url.String.startsWith(searchString: string, position?: number): boolean
Returns true if the sequence of elements of searchString converted to a String is the
same as the corresponding elements of this object (converted to a String) starting at
position. Otherwise returns false.
startsWith('https://api.my-domain.com/')) {
request: Request
request.Request.headers: Headers
Returns a Headers object consisting of the headers associated with request. Note that headers added in the network layer by the user agent will not be accounted for in this object, e.g., the “Host” header.
headers.Headers.set(name: string, value: string): void
set('cookie', event: RequestEvent<Partial<Record<string, string>>, string | null>
event.RequestEvent<Partial<Record<string, string>>, string | null>.request: Request
The original request object
request.Request.headers: Headers
Returns a Headers object consisting of the headers associated with request. Note that headers added in the network layer by the user agent will not be accounted for in this object, e.g., the “Host” header.
headers.Headers.get(name: string): string | null
get('cookie'));
}
return fetch: (input: string | URL | globalThis.Request, init?: RequestInit) => Promise<Response> (+1 overload)
fetch(request: Request
request);
};
共享 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,供用户在与技术支持人员通信时引用:
declare global {
namespace App {
interface interface App.Error
Defines the common shape of expected and unexpected errors. Expected errors are thrown using the error
function. Unexpected errors are handled by the handleError
hooks which should return this shape.
Error {
App.Error.message: string
message: string;
App.Error.errorId: string
errorId: string;
}
}
}
export {};
import * as module "@sentry/sveltekit"
Sentry from '@sentry/sveltekit';
module "@sentry/sveltekit"
Sentry.const init: (opts: any) => void
init({/*...*/})
/** @type {import('@sveltejs/kit').HandleServerError} */
export async function function handleError(input: {
error: unknown;
event: RequestEvent;
status: number;
message: string;
}): MaybePromise<void | App.Error>
handleError({ error: unknown
error, event: RequestEvent<Partial<Record<string, string>>, string | null>
event, status: number
status, message: string
message }) {
const const errorId: `${string}-${string}-${string}-${string}-${string}`
errorId = var crypto: Crypto
crypto.Crypto.randomUUID(): `${string}-${string}-${string}-${string}-${string}`
Available only in secure contexts.
randomUUID();
// 与 https://sentry.io/ 集成的示例
module "@sentry/sveltekit"
Sentry.const captureException: (error: any, opts: any) => void
captureException(error: unknown
error, {
extra: {
event: RequestEvent<Partial<Record<string, string>>, string | null>;
errorId: `${string}-${string}-${string}-${string}-${string}`;
status: number;
}
extra: { event: RequestEvent<Partial<Record<string, string>>, string | null>
event, errorId: `${string}-${string}-${string}-${string}-${string}`
errorId, status: number
status }
});
return {
App.Error.message: string
message: '哎呀!',
errorId: `${string}-${string}-${string}-${string}-${string}`
errorId
};
}
import * as module "@sentry/sveltekit"
Sentry from '@sentry/sveltekit';
import type { type HandleServerError = (input: {
error: unknown;
event: RequestEvent;
status: number;
message: string;
}) => MaybePromise<void | App.Error>
The server-side handleError
hook runs when an unexpected error is thrown while responding to a request.
If an unexpected error is thrown during loading or rendering, this function will be called with the error and the event.
Make sure that this function never throws an error.
HandleServerError } from '@sveltejs/kit';
module "@sentry/sveltekit"
Sentry.const init: (opts: any) => void
init({/*...*/})
export const const handleError: HandleServerError
handleError: type HandleServerError = (input: {
error: unknown;
event: RequestEvent;
status: number;
message: string;
}) => MaybePromise<void | App.Error>
The server-side handleError
hook runs when an unexpected error is thrown while responding to a request.
If an unexpected error is thrown during loading or rendering, this function will be called with the error and the event.
Make sure that this function never throws an error.
HandleServerError = async ({ error: unknown
error, event: RequestEvent<Partial<Record<string, string>>, string | null>
event, status: number
status, message: string
message }) => {
const const errorId: `${string}-${string}-${string}-${string}-${string}`
errorId = var crypto: Crypto
crypto.Crypto.randomUUID(): `${string}-${string}-${string}-${string}-${string}`
Available only in secure contexts.
randomUUID();
// 与 https://sentry.io/ 集成的示例
module "@sentry/sveltekit"
Sentry.const captureException: (error: any, opts: any) => void
captureException(error: unknown
error, {
extra: {
event: RequestEvent<Partial<Record<string, string>>, string | null>;
errorId: `${string}-${string}-${string}-${string}-${string}`;
status: number;
}
extra: { event: RequestEvent<Partial<Record<string, string>>, string | null>
event, errorId: `${string}-${string}-${string}-${string}-${string}`
errorId, status: number
status }
});
return {
App.Error.message: string
message: '哎呀!',
errorId: `${string}-${string}-${string}-${string}-${string}`
errorId
};
};
import * as module "@sentry/sveltekit"
Sentry from '@sentry/sveltekit';
module "@sentry/sveltekit"
Sentry.const init: (opts: any) => void
init({/*...*/})
/** @type {import('@sveltejs/kit').HandleClientError} */
export async function function handleError(input: {
error: unknown;
event: NavigationEvent;
status: number;
message: string;
}): MaybePromise<void | App.Error>
handleError({ error: unknown
error, event: NavigationEvent<Partial<Record<string, string>>, string | null>
event, status: number
status, message: string
message }) {
const const errorId: `${string}-${string}-${string}-${string}-${string}`
errorId = var crypto: Crypto
crypto.Crypto.randomUUID(): `${string}-${string}-${string}-${string}-${string}`
Available only in secure contexts.
randomUUID();
// 与 https://sentry.io/ 集成的示例
module "@sentry/sveltekit"
Sentry.const captureException: (error: any, opts: any) => void
captureException(error: unknown
error, {
extra: {
event: NavigationEvent<Partial<Record<string, string>>, string | null>;
errorId: `${string}-${string}-${string}-${string}-${string}`;
status: number;
}
extra: { event: NavigationEvent<Partial<Record<string, string>>, string | null>
event, errorId: `${string}-${string}-${string}-${string}-${string}`
errorId, status: number
status }
});
return {
App.Error.message: string
message: '哎呀!',
errorId: `${string}-${string}-${string}-${string}-${string}`
errorId
};
}
import * as module "@sentry/sveltekit"
Sentry from '@sentry/sveltekit';
import type { type HandleClientError = (input: {
error: unknown;
event: NavigationEvent;
status: number;
message: string;
}) => MaybePromise<void | App.Error>
The client-side handleError
hook runs when an unexpected error is thrown while navigating.
If an unexpected error is thrown during loading or the following render, this function will be called with the error and the event.
Make sure that this function never throws an error.
HandleClientError } from '@sveltejs/kit';
module "@sentry/sveltekit"
Sentry.const init: (opts: any) => void
init({/*...*/})
export const const handleError: HandleClientError
handleError: type HandleClientError = (input: {
error: unknown;
event: NavigationEvent;
status: number;
message: string;
}) => MaybePromise<void | App.Error>
The client-side handleError
hook runs when an unexpected error is thrown while navigating.
If an unexpected error is thrown during loading or the following render, this function will be called with the error and the event.
Make sure that this function never throws an error.
HandleClientError = async ({ error: unknown
error, event: NavigationEvent<Partial<Record<string, string>>, string | null>
event, status: number
status, message: string
message }) => {
const const errorId: `${string}-${string}-${string}-${string}-${string}`
errorId = var crypto: Crypto
crypto.Crypto.randomUUID(): `${string}-${string}-${string}-${string}-${string}`
Available only in secure contexts.
randomUUID();
// 与 https://sentry.io/ 集成的示例
module "@sentry/sveltekit"
Sentry.const captureException: (error: any, opts: any) => void
captureException(error: unknown
error, {
extra: {
event: NavigationEvent<Partial<Record<string, string>>, string | null>;
errorId: `${string}-${string}-${string}-${string}-${string}`;
status: number;
}
extra: { event: NavigationEvent<Partial<Record<string, string>>, string | null>
event, errorId: `${string}-${string}-${string}-${string}-${string}`
errorId, status: number
status }
});
return {
App.Error.message: string
message: '哎呀!',
errorId: `${string}-${string}-${string}-${string}-${string}`
errorId
};
};
在
src/hooks.client.js
中,handleError
的类型是HandleClientError
而不是HandleServerError
,并且event
是一个NavigationEvent
而不是RequestEvent
。
此函数不会因为预期的错误(那些使用从 @sveltejs/kit
导入的 error
函数抛出的错误)而被调用。
在开发过程中,如果由于 Svelte 代码中的语法错误而发生错误,传入的错误会附加一个 frame
属性,突出显示错误的位置。
确保
handleError
永远不会抛出错误
init
这个函数在服务端创建或应用程序在浏览器中启动时运行一次,是执行异步工作(如初始化数据库连接)的有用位置。
如果您的环境支持顶级 await,
init
函数实际上与在模块顶层编写初始化逻辑没有什么不同,但一些环境 — 尤其是 Safari — 不支持。
import * as import db
db from '$lib/server/database';
/** @type {import('@sveltejs/kit').ServerInit} */
export async function function init(): Promise<void>
init() {
await import db
db.connect();
}
import * as import db
db from '$lib/server/database';
import type { type ServerInit = () => MaybePromise<void>
The init
will be invoked before the server responds to its first request
ServerInit } from '@sveltejs/kit';
export const const init: ServerInit
init: type ServerInit = () => MaybePromise<void>
The init
will be invoked before the server responds to its first request
ServerInit = async () => {
await import db
db.connect();
};
在浏览器中,
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
来实现:
/** @type {Record<string, string>} */
const const translated: {
'/en/about': string;
'/de/ueber-uns': string;
'/fr/a-propos': string;
}
translated = {
'/en/about': '/en/about',
'/de/ueber-uns': '/de/about',
'/fr/a-propos': '/fr/about'
};
/** @type {import('@sveltejs/kit').Reroute} */
export function function reroute({ url }: {
url: any;
}): any
reroute({ url: any
url }) {
if (url: any
url.pathname in const translated: {
'/en/about': string;
'/de/ueber-uns': string;
'/fr/a-propos': string;
}
translated) {
return const translated: {
'/en/about': string;
'/de/ueber-uns': string;
'/fr/a-propos': string;
}
translated[url: any
url.pathname];
}
}
import type { type Reroute = (event: {
url: URL;
}) => void | string
The reroute
hook allows you to modify the URL before it is used to determine which route to render.
Reroute } from '@sveltejs/kit';
const const translated: Record<string, string>
translated: type Record<K extends keyof any, T> = { [P in K]: T; }
Construct a type with a set of properties K of type T
Record<string, string> = {
'/en/about': '/en/about',
'/de/ueber-uns': '/de/about',
'/fr/a-propos': '/fr/about'
};
export const const reroute: Reroute
reroute: type Reroute = (event: {
url: URL;
}) => void | string
The reroute
hook allows you to modify the URL before it is used to determine which route to render.
Reroute = ({ url: URL
url }) => {
if (url: URL
url.URL.pathname: string
pathname in const translated: Record<string, string>
translated) {
return const translated: Record<string, string>
translated[url: URL
url.URL.pathname: string
pathname];
}
};
lang
参数将从返回的路径名正确派生。
使用 reroute
不会改变浏览器地址栏的内容,也不会改变 event.url
的值。
传输
这是一组 传输器,允许您跨服务端/客户端边界传递自定义类型 - 从 load
和 form actions 返回的类型。每个传输器都包含一个 encode
函数,该函数对服务端上的值进行编码(或对任何不是该类型的实例返回 false),以及一个相应的 decode
函数:
import { import Vector
Vector } from '$lib/math';
/** @type {import('@sveltejs/kit').Transport} */
export const const transport: {
Vector: {
encode: (value: any) => false | any[];
decode: ([x, y]: [any, any]) => any;
};
}
transport = {
type Vector: {
encode: (value: any) => false | any[];
decode: ([x, y]: [any, any]) => any;
}
Vector: {
encode: (value: any) => false | any[]
encode: (value: any
value) => value: any
value instanceof import Vector
Vector && [value: any
value.x, value: any
value.y],
decode: ([x, y]: [any, any]) => any
decode: ([x: any
x, y: any
y]) => new import Vector
Vector(x: any
x, y: any
y)
}
};
import { import Vector
Vector } from '$lib/math';
import type { type Transport = {
[x: string]: Transporter<any, any>;
}
The transport
hook allows you to transport custom types across the server/client boundary.
Each transporter has a pair of encode
and decode
functions. On the server, encode
determines whether a value is an instance of the custom type and, if so, returns a non-falsy encoding of the value which can be an object or an array (or false
otherwise).
In the browser, decode
turns the encoding back into an instance of the custom type.
import type { Transport } from '@sveltejs/kit';
declare class MyCustomType {
data: any
}
// hooks.js
export const transport: Transport = {
MyCustomType: {
encode: (value) => value instanceof MyCustomType && [value.data],
decode: ([data]) => new MyCustomType(data)
}
};
Transport } from '@sveltejs/kit';
export const const transport: Transport
transport: type Transport = {
[x: string]: Transporter<any, any>;
}
The transport
hook allows you to transport custom types across the server/client boundary.
Each transporter has a pair of encode
and decode
functions. On the server, encode
determines whether a value is an instance of the custom type and, if so, returns a non-falsy encoding of the value which can be an object or an array (or false
otherwise).
In the browser, decode
turns the encoding back into an instance of the custom type.
import type { Transport } from '@sveltejs/kit';
declare class MyCustomType {
data: any
}
// hooks.js
export const transport: Transport = {
MyCustomType: {
encode: (value) => value instanceof MyCustomType && [value.data],
decode: ([data]) => new MyCustomType(data)
}
};
Transport = {
type Vector: {
encode: (value: any) => false | any[];
decode: ([x, y]: any) => any;
}
Vector: {
Transporter<any, any>.encode: (value: any) => any
encode: (value: any
value) => value: any
value instanceof import Vector
Vector && [value: any
value.x, value: any
value.y],
Transporter<any, any>.decode: (data: any) => any
decode: ([x: any
x, y: any
y]) => new import Vector
Vector(x: any
x, y: any
y)
}
};