Hooks
‘Hooks’ は、特定のイベントに対して SvelteKit がレスポンスを呼び出すことを宣言するアプリ全体の関数で、これによってフレームワークの動作をきめ細やかに制御できるようになります。
hooks ファイルは2つあり、どちらもオプションです:
src/hooks.server.js— アプリのサーバーの hookssrc/hooks.client.js— アプリのクライアントの hookssrc/hooks.js— サーバーとクライアントの両方で実行される hooks
これらのモジュールのコードはアプリケーションの起動時に実行されるので、データベースクライアントの初期化などに有用です。
これらのファイルの場所は
config.kit.files.hooksで設定できます。
Server hooks
以下の hooks は src/hooks.server.js に追加することができます:
handle
この関数は SvelteKit のサーバーが リクエスト を受けるたびに (アプリの実行中であろうと、プリレンダリングであろうと) 実行され、レスポンス を決定します。リクエストを表す event オブジェクトと、ルート(route)をレンダリングしレスポンスを生成する resolve という関数を受け取ります。これにより、レスポンスのヘッダーやボディを変更したり、SvelteKitを完全にバイパスすることができます (例えば、プログラムでルート(routes)を実装する場合など)。
/** @type {import('@sveltejs/kit').Handle} */
export async function function handle({ event, resolve }: {
event: any;
resolve: any;
}): Promise<any>
handle({ event: anyevent, resolve: anyresolve }) {
if (event: anyevent.url.pathname.startsWith('/custom')) {
return new var Response: new (body?: BodyInit | null, init?: ResponseInit) => ResponseThis Fetch API interface represents the response to a request.
Response('custom response');
}
const const response: anyresponse = await resolve: anyresolve(event: anyevent);
return const response: anyresponse;
}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: Handlehandle: 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<Record<string, string>, string | null>event, resolve: (event: RequestEvent, opts?: ResolveOptions) => MaybePromise<Response>resolve }) => {
if (event: RequestEvent<Record<string, string>, string | null>event.RequestEvent<Record<string, string>, string | null>.url: URLThe requested URL.
url.URL.pathname: stringpathname.String.startsWith(searchString: string, position?: number): booleanReturns 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) => ResponseThis Fetch API interface represents the response to a request.
Response('custom response');
}
const const response: Responseresponse = await resolve: (event: RequestEvent, opts?: ResolveOptions) => MaybePromise<Response>resolve(event: RequestEvent<Record<string, string>, string | null>event);
return const response: Responseresponse;
};静的アセット(プリレンダリング済みのページを含む)に対するリクエストは SvelteKit では処理されません。
未実装の場合、デフォルトは ({ event, resolve }) => resolve(event) となります。
During prerendering, SvelteKit crawls your pages for links and renders each route it finds. Rendering the route invokes the handle function (and all other route dependencies, like load). If you need to exclude some code from running during this phase, check that the app is not building beforehand.
locals
カスタムデータをリクエストに追加し、+server.js のハンドラや server 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<Record<string, string>, string | null>event, resolve: (event: RequestEvent, opts?: ResolveOptions) => MaybePromise<Response>resolve }) {
event: RequestEvent<Record<string, string>, string | null>event.RequestEvent<Record<string, string>, string | null>.locals: App.LocalsContains custom data that was added to the request within the server handle hook.
locals.App.Locals.user: Useruser = await const getUserInformation: (cookie: string | void) => Promise<User>getUserInformation(event: RequestEvent<Record<string, string>, string | null>event.RequestEvent<Record<string, string>, string | null>.cookies: CookiesGet or set cookies related to the current request
cookies.Cookies.get: (name: string, opts?: CookieParseOptions) => string | undefinedGets a cookie that was previously set with cookies.set, or from the request headers.
get('sessionid'));
const const response: Responseresponse = await resolve: (event: RequestEvent, opts?: ResolveOptions) => MaybePromise<Response>resolve(event: RequestEvent<Record<string, string>, string | null>event);
// Note that modifying response headers isn't always safe.
// Response objects can have immutable headers
// (e.g. Response.redirect() returned from an endpoint).
// Modifying immutable headers throws a TypeError.
// In that case, clone the response or avoid creating a
// response object with immutable headers.
const response: Responseresponse.Response.headers: Headersheaders.Headers.set(name: string, value: string): voidset('x-custom-header', 'potato');
return const response: Responseresponse;
}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: Handlehandle: 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<Record<string, string>, string | null>event, resolve: (event: RequestEvent, opts?: ResolveOptions) => MaybePromise<Response>resolve }) => {
event: RequestEvent<Record<string, string>, string | null>event.RequestEvent<Record<string, string>, string | null>.locals: App.LocalsContains custom data that was added to the request within the server handle hook.
locals.App.Locals.user: Useruser = await const getUserInformation: (cookie: string | void) => Promise<User>getUserInformation(event: RequestEvent<Record<string, string>, string | null>event.RequestEvent<Record<string, string>, string | null>.cookies: CookiesGet or set cookies related to the current request
cookies.Cookies.get: (name: string, opts?: CookieParseOptions) => string | undefinedGets a cookie that was previously set with cookies.set, or from the request headers.
get('sessionid'));
const const response: Responseresponse = await resolve: (event: RequestEvent, opts?: ResolveOptions) => MaybePromise<Response>resolve(event: RequestEvent<Record<string, string>, string | null>event);
// Note that modifying response headers isn't always safe.
// Response objects can have immutable headers
// (e.g. Response.redirect() returned from an endpoint).
// Modifying immutable headers throws a TypeError.
// In that case, clone the response or avoid creating a
// response object with immutable headers.
const response: Responseresponse.Response.headers: Headersheaders.Headers.set(name: string, value: string): voidset('x-custom-header', 'potato');
return const response: Responseresponse;
};sequence ヘルパー関数を使用すると、複数の handle 関数を定義することができます。
resolve はオプションの第2引数をサポートしており、レスポンスのレンダリング方法をより詳細にコントロールすることができます。そのパラメータは、以下のフィールドを持つオブジェクトです:
transformPageChunk(opts: { html: string, done: boolean }): MaybePromise<string | undefined>— カスタムの変換を HTML に適用します。doneが true である場合、それは最後のチャンクです。チャンクが整形された HTML であることは保証されませんが (例えば、要素の開始タグは含むが終了タグは含まれない、など)、常に%sveltekit.head%やレイアウト(layout)/ページ(page)コンポーネントなどのような理にかなった境界 (sensible boundaries) で分割されます。filterSerializedResponseHeaders(name: string, value: string): boolean—load関数がfetchでリソースを読み込むときに、シリアライズされるレスポンスにどのヘッダーを含めるかを決定します。デフォルトでは何も含まれません。preload(input: { type: 'js' | 'css' | 'font' | 'asset', path: string }): boolean—<head>タグにどのファイルをプリロードの対象として追加するか決定します。このメソッドはビルド時、コードチャンクを構築している際に見つかったファイルごとに呼び出されます。これにより、例えば+page.svelteにimport './styles.cssがある場合、そのページに訪れたときにその CSS ファイルへの解決されたパスを以てpreloadが呼び出されるようになります。これはビルド時の分析によって行われるため、開発モードではpreloadが呼ばれないことにご注意ください。プリロードによってその対象がより早くダウンロードされるようになるためパフォーマンスが改善しますが、不必要に多くのものをダウンロードしてしまうと、core web vitals を悪化させてしまいます。デフォルトでは、js、cssファイルがプリロードされます。現時点ではassetファイルはプリロードされませんが、フィードバックによっては追加されるかもしれません。
/** @type {import('@sveltejs/kit').Handle} */
export async function function handle({ event, resolve }: {
event: any;
resolve: any;
}): Promise<any>
handle({ event: anyevent, resolve: anyresolve }) {
const const response: anyresponse = await resolve: anyresolve(event: anyevent, {
transformPageChunk: ({ html }: {
html: any;
}) => any
transformPageChunk: ({ html: anyhtml }) => html: anyhtml.replace('old', 'new'),
filterSerializedResponseHeaders: (name: any) => anyfilterSerializedResponseHeaders: (name: anyname) => name: anyname.startsWith('x-'),
preload: ({ type, path }: {
type: any;
path: any;
}) => any
preload: ({ type: anytype, path: anypath }) => type: anytype === 'js' || path: anypath.includes('/important/')
});
return const response: anyresponse;
}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: Handlehandle: 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<Record<string, string>, string | null>event, resolve: (event: RequestEvent, opts?: ResolveOptions) => MaybePromise<Response>resolve }) => {
const const response: Responseresponse = await resolve: (event: RequestEvent, opts?: ResolveOptions) => MaybePromise<Response>resolve(event: RequestEvent<Record<string, string>, string | null>event, {
ResolveOptions.transformPageChunk?: ((input: {
html: string;
done: boolean;
}) => MaybePromise<string | undefined>) | 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: stringhtml }) => html: stringhtml.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) | undefinedDetermines 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: stringname) => name: stringname.String.startsWith(searchString: string, position?: number): booleanReturns 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) | undefined
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: stringpath }) => type: "font" | "css" | "js" | "asset"type === 'js' || path: stringpath.String.includes(searchString: string, position?: number): booleanReturns 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: Responseresponse;
};resolve(...) は決してエラーをスローせず、適切なステータスコードと Promise<Response> を返すことにご注意ください。もし handle 中に他の場所でエラーがスローされた場合、それは致命的(fatal)なものとして扱われ、SvelteKit は Accept ヘッダーに応じて、そのエラーの JSON 表現か、src/error.html でカスタマイズ可能なフォールバックエラーページをレスポンスとして返します。エラーハンドリングの詳細は こちら からお読み頂けます。
handleFetch
この関数は、サーバー上で (またはプリレンダリング中に) 実行される load 関数や action 関数の中で発生する fetch リクエストを変更 (または置換) することできます。
例えば、ユーザーがクライアントサイドでそれぞれのページに移動する際に、load 関数で https://api.yourapp.com のようなパブリックな URL にリクエストを行うかもしれませんが、SSR の場合には (パブリックなインターネットとの間にあるプロキシやロードバランサーをバイパスして) API を直接呼ぶほうが理にかなっているでしょう。
/** @type {import('@sveltejs/kit').HandleFetch} */
export async function function handleFetch({ request, fetch }: {
request: any;
fetch: any;
}): Promise<any>
handleFetch({ request: anyrequest, fetch: anyfetch }) {
if (request: anyrequest.url.startsWith('https://api.yourapp.com/')) {
// clone the original request, but change the URL
request: anyrequest = new var Request: new (input: RequestInfo | URL, init?: RequestInit) => RequestThis Fetch API interface represents a resource request.
Request(
request: anyrequest.url.replace('https://api.yourapp.com/', 'http://localhost:9999/'),
request: anyrequest
);
}
return fetch: anyfetch(request: anyrequest);
}import type { type HandleFetch = (input: {
event: RequestEvent;
request: Request;
fetch: typeof fetch;
}) => MaybePromise<Response>
The handleFetch hook allows you to modify (or replace) the result of an event.fetch call that runs on the server (or during prerendering) inside an endpoint, load, action, handle, handleError or reroute.
HandleFetch } from '@sveltejs/kit';
export const const handleFetch: HandleFetchhandleFetch: type HandleFetch = (input: {
event: RequestEvent;
request: Request;
fetch: typeof fetch;
}) => MaybePromise<Response>
The handleFetch hook allows you to modify (or replace) the result of an event.fetch call that runs on the server (or during prerendering) inside an endpoint, load, action, handle, handleError or reroute.
HandleFetch = async ({ request: Requestrequest, fetch: {
(input: RequestInfo | URL, init?: RequestInit): Promise<Response>;
(input: string | URL | globalThis.Request, init?: RequestInit): Promise<Response>;
}
fetch }) => {
if (request: Requestrequest.Request.url: stringReturns the URL of request as a string.
url.String.startsWith(searchString: string, position?: number): booleanReturns 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/')) {
// clone the original request, but change the URL
request: Requestrequest = new var Request: new (input: RequestInfo | URL, init?: RequestInit) => RequestThis Fetch API interface represents a resource request.
Request(
request: Requestrequest.Request.url: stringReturns 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: Requestrequest
);
}
return fetch: (input: string | URL | globalThis.Request, init?: RequestInit) => Promise<Response> (+1 overload)fetch(request: Requestrequest);
};event.fetch で作られた Request はブラウザのクレデンシャルモデルに従います — 同一オリジン(same-origin)に対する Request の場合、credentials オプションに "omit" が設定されていない限り、cookie と authorization ヘッダーは転送されます。クロスオリジン(cross-origin)に対する Request の場合、その Request の URL がアプリのサブドメインである場合、cookie はその Request に含まれます。例えば、もしアプリの URL が my-domain.com で、API の URL が api.my-domain.com である場合、cookie はその Request に含まれるということです。
1つ注意点があります: もしあなたのアプリと 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: anyevent, request: anyrequest, fetch: anyfetch }) {
if (request: anyrequest.url.startsWith('https://api.my-domain.com/')) {
request: anyrequest.headers.set('cookie', event: anyevent.request.headers.get('cookie'));
}
return fetch: anyfetch(request: anyrequest);
}import type { type HandleFetch = (input: {
event: RequestEvent;
request: Request;
fetch: typeof fetch;
}) => MaybePromise<Response>
The handleFetch hook allows you to modify (or replace) the result of an event.fetch call that runs on the server (or during prerendering) inside an endpoint, load, action, handle, handleError or reroute.
HandleFetch } from '@sveltejs/kit';
export const const handleFetch: HandleFetchhandleFetch: type HandleFetch = (input: {
event: RequestEvent;
request: Request;
fetch: typeof fetch;
}) => MaybePromise<Response>
The handleFetch hook allows you to modify (or replace) the result of an event.fetch call that runs on the server (or during prerendering) inside an endpoint, load, action, handle, handleError or reroute.
HandleFetch = async ({ event: RequestEvent<Record<string, string>, string | null>event, request: Requestrequest, fetch: {
(input: RequestInfo | URL, init?: RequestInit): Promise<Response>;
(input: string | URL | globalThis.Request, init?: RequestInit): Promise<Response>;
}
fetch }) => {
if (request: Requestrequest.Request.url: stringReturns the URL of request as a string.
url.String.startsWith(searchString: string, position?: number): booleanReturns 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: Requestrequest.Request.headers: HeadersReturns 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): voidset('cookie', event: RequestEvent<Record<string, string>, string | null>event.RequestEvent<Record<string, string>, string | null>.request: RequestThe original request object.
request.Request.headers: HeadersReturns 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 | nullget('cookie'));
}
return fetch: (input: string | URL | globalThis.Request, init?: RequestInit) => Promise<Response> (+1 overload)fetch(request: Requestrequest);
};handleValidationError
This hook is called when a remote function is called with an argument that does not match the provided Standard Schema. It must return an object matching the shape of App.Error.
Say you have a remote function that expects a string as its argument ...
import * as import vv from 'valibot';
import { function query<Output>(fn: () => MaybePromise<Output>): RemoteQueryFunction<void, Output> (+2 overloads)Creates a remote query. When called from the browser, the function will be invoked on the server via a fetch call.
See Remote functions for full documentation.
query } from '$app/server';
export const const getTodo: RemoteQueryFunction<string, void>getTodo = query<v.StringSchema<undefined>, void>(schema: v.StringSchema<undefined>, fn: (arg: string) => MaybePromise<void>): RemoteQueryFunction<string, void> (+2 overloads)Creates a remote query. When called from the browser, the function will be invoked on the server via a fetch call.
See Remote functions for full documentation.
query(import vv.function string(): v.StringSchema<undefined> (+1 overload)
export string
Creates a string schema.
string(), (id: stringid) => {
// implementation...
});...but it is called with something that doesn’t match the schema — such as a number (e.g await getTodos(1)) — then validation will fail, the server will respond with a 400 status code, and the function will throw with the message ‘Bad Request’.
To customise this message and add additional properties to the error object, implement handleValidationError:
/** @type {import('@sveltejs/kit').HandleValidationError} */
export function function handleValidationError({ issues }: {
issues: any;
}): {
message: string;
}
handleValidationError({ issues: anyissues }) {
return {
message: stringmessage: 'No thank you'
};
}import type { type HandleValidationError<Issue extends StandardSchemaV1.Issue = StandardSchemaV1.Issue> = (input: {
issues: Issue[];
event: RequestEvent;
}) => MaybePromise<App.Error>
The handleValidationError hook runs when the argument to a remote function fails validation.
It will be called with the validation issues and the event, and must return an object shape that matches App.Error.
HandleValidationError } from '@sveltejs/kit';
export const const handleValidationError: HandleValidationErrorhandleValidationError: type HandleValidationError<Issue extends StandardSchemaV1.Issue = StandardSchemaV1.Issue> = (input: {
issues: Issue[];
event: RequestEvent;
}) => MaybePromise<App.Error>
The handleValidationError hook runs when the argument to a remote function fails validation.
It will be called with the validation issues and the event, and must return an object shape that matches App.Error.
HandleValidationError = ({ issues: StandardSchemaV1.Issue[]issues }) => {
return {
App.Error.message: stringmessage: 'No thank you'
};
};Be thoughtful about what information you expose here, as the most likely reason for validation to fail is that someone is sending malicious requests to your server.
Shared hooks
以下は src/hooks.server.js と src/hooks.client.js のどちらにも追加できます:
handleError
予期せぬエラーが、ロード中やレンダリング中、またはエンドポイントからスローされると、この関数が error、event、status コード、message を引数にとって呼び出されます。これによって以下の2つのことが可能になります:
- エラーをログに残すことができます
- エラーからメッセージやスタックトレースなどの機密情報を省略し、ユーザーに見せても安全なカスタムの表現を生成することができます。戻り値のデフォルトは
{ message }で、$page.errorの値となります。
あなたのコード (またはあなたのコードから呼び出されたライブラリのコード) からスローされたエラーの場合、ステータスは 500 となり、message は “Internal Error” になります。error.message にはユーザーに公開されるべきではない機密情報が含まれている可能性がありますが、message は安全です (一般的なユーザーにとっては無意味ではありますが)。
$page.error オブジェクトに型安全な方法で情報を追加するには、App.Error interface を宣言することで想定する形にすることができます (適切なフォールバックの動作を保証するため、message: string を含む必要があります)。これにより、例えばユーザーがテクニカルサポートスタッフとの対応の際に引用することができるトラッキング ID を付加することができます:
declare global {
namespace App {
interface interface App.ErrorDefines 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: stringmessage: string;
App.Error.errorId: stringerrorId: string;
}
}
}
export {};import * as module "@sentry/sveltekit"Sentry from '@sentry/sveltekit';
module "@sentry/sveltekit"Sentry.const init: (opts: any) => voidinit({/*...*/})
/** @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: unknownerror, event: RequestEvent<Record<string, string>, string | null>event, status: numberstatus, message: stringmessage }) {
const const errorId: `${string}-${string}-${string}-${string}-${string}`errorId = var crypto: Cryptocrypto.Crypto.randomUUID(): `${string}-${string}-${string}-${string}-${string}`Available only in secure contexts.
randomUUID();
// example integration with https://sentry.io/
module "@sentry/sveltekit"Sentry.const captureException: (error: any, opts: any) => voidcaptureException(error: unknownerror, {
extra: {
event: RequestEvent<Record<string, string>, string | null>;
errorId: `${string}-${string}-${string}-${string}-${string}`;
status: number;
}
extra: { event: RequestEvent<Record<string, string>, string | null>event, errorId: `${string}-${string}-${string}-${string}-${string}`errorId, status: numberstatus }
});
return {
App.Error.message: stringmessage: 'Whoops!',
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) => voidinit({/*...*/})
export const const handleError: HandleServerErrorhandleError: 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: unknownerror, event: RequestEvent<Record<string, string>, string | null>event, status: numberstatus, message: stringmessage }) => {
const const errorId: `${string}-${string}-${string}-${string}-${string}`errorId = var crypto: Cryptocrypto.Crypto.randomUUID(): `${string}-${string}-${string}-${string}-${string}`Available only in secure contexts.
randomUUID();
// example integration with https://sentry.io/
module "@sentry/sveltekit"Sentry.const captureException: (error: any, opts: any) => voidcaptureException(error: unknownerror, {
extra: {
event: RequestEvent<Record<string, string>, string | null>;
errorId: `${string}-${string}-${string}-${string}-${string}`;
status: number;
}
extra: { event: RequestEvent<Record<string, string>, string | null>event, errorId: `${string}-${string}-${string}-${string}-${string}`errorId, status: numberstatus }
});
return {
App.Error.message: stringmessage: 'Whoops!',
errorId: `${string}-${string}-${string}-${string}-${string}`errorId
};
};import * as module "@sentry/sveltekit"Sentry from '@sentry/sveltekit';
module "@sentry/sveltekit"Sentry.const init: (opts: any) => voidinit({/*...*/})
/** @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: unknownerror, event: NavigationEvent<Record<string, string>, string | null>event, status: numberstatus, message: stringmessage }) {
const const errorId: `${string}-${string}-${string}-${string}-${string}`errorId = var crypto: Cryptocrypto.Crypto.randomUUID(): `${string}-${string}-${string}-${string}-${string}`Available only in secure contexts.
randomUUID();
// example integration with https://sentry.io/
module "@sentry/sveltekit"Sentry.const captureException: (error: any, opts: any) => voidcaptureException(error: unknownerror, {
extra: {
event: NavigationEvent<Record<string, string>, string | null>;
errorId: `${string}-${string}-${string}-${string}-${string}`;
status: number;
}
extra: { event: NavigationEvent<Record<string, string>, string | null>event, errorId: `${string}-${string}-${string}-${string}-${string}`errorId, status: numberstatus }
});
return {
App.Error.message: stringmessage: 'Whoops!',
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) => voidinit({/*...*/})
export const const handleError: HandleClientErrorhandleError: 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: unknownerror, event: NavigationEvent<Record<string, string>, string | null>event, status: numberstatus, message: stringmessage }) => {
const const errorId: `${string}-${string}-${string}-${string}-${string}`errorId = var crypto: Cryptocrypto.Crypto.randomUUID(): `${string}-${string}-${string}-${string}-${string}`Available only in secure contexts.
randomUUID();
// example integration with https://sentry.io/
module "@sentry/sveltekit"Sentry.const captureException: (error: any, opts: any) => voidcaptureException(error: unknownerror, {
extra: {
event: NavigationEvent<Record<string, string>, string | null>;
errorId: `${string}-${string}-${string}-${string}-${string}`;
status: number;
}
extra: { event: NavigationEvent<Record<string, string>, string | null>event, errorId: `${string}-${string}-${string}-${string}-${string}`errorId, status: numberstatus }
});
return {
App.Error.message: stringmessage: 'Whoops!',
errorId: `${string}-${string}-${string}-${string}-${string}`errorId
};
};
src/hooks.client.jsでは、handleErrorの型はHandleServerErrorではなくHandleClientErrorで、eventはRequestEventではなくNavigationEventです。
この関数は 想定される エラー (@sveltejs/kit からインポートされる error 関数でスローされるエラー) の場合は呼び出されません。
開発中、Svelte のコードの構文エラーでエラーが発生した場合、渡される error には、エラーの場所のハイライトが付与された frame プロパティがあります。
handleError自体が決してエラーをスローしないようにしてください。
init
This function runs once, when the server is created or the app starts in the browser, and is a useful place to do asynchronous work such as initializing a database connection.
If your environment supports top-level await, the
initfunction is really no different from writing your initialisation logic at the top level of the module, but some environments — most notably, Safari — don’t.
import * as import dbdb from '$lib/server/database';
/** @type {import('@sveltejs/kit').ServerInit} */
export async function function init(): Promise<void>init() {
await import dbdb.connect();
}import * as import dbdb 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: ServerInitinit: type ServerInit = () => MaybePromise<void>The init will be invoked before the server responds to its first request
ServerInit = async () => {
await import dbdb.connect();
};In the browser, asynchronous work in
initwill delay hydration, so be mindful of what you put in there.
Universal hooks
以下は src/hooks.js に追加することができます。universal hooks はサーバーとクライアントの両方で実行されます (shared hooks と混同しないようにしてください、shared hooks は環境依存です)。
reroute
この関数は handle より前に実行され、URL をルート(route)に変換する方法を変更することができます。戻り値の pathname (デフォルトは url.pathname) はルート(route)パラメータを選択するのに使用されます。
例えば、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: anyurl }) {
if (url: anyurl.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: anyurl.pathname];
}
}import type { type Reroute = (event: {
url: URL;
fetch: typeof fetch;
}) => MaybePromise<string | void>
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: Reroutereroute: type Reroute = (event: {
url: URL;
fetch: typeof fetch;
}) => MaybePromise<string | void>
The reroute hook allows you to modify the URL before it is used to determine which route to render.
Reroute = ({ url: URLurl }) => {
if (url: URLurl.URL.pathname: stringpathname in const translated: Record<string, string>translated) {
return const translated: Record<string, string>translated[url: URLurl.URL.pathname: stringpathname];
}
};lang パラメータは戻り値の pathname から正しく導くことができます。
reroute を使用してもブラウザのアドレスバーの内容や event.url の値は変更されません。
Since version 2.18, the reroute hook can be asynchronous, allowing it to (for example) fetch data from your backend to decide where to reroute to. Use this carefully and make sure it’s fast, as it will delay navigation otherwise. If you need to fetch data, use the fetch provided as an argument. It has the same benefits as the fetch provided to load functions, with the caveat that params and id are unavailable to handleFetch because the route is not yet known.
/** @type {import('@sveltejs/kit').Reroute} */
export async function function reroute({ url, fetch }: {
url: any;
fetch: any;
}): Promise<any>
reroute({ url: anyurl, fetch: anyfetch }) {
// Ask a special endpoint within your app about the destination
if (url: anyurl.pathname === '/api/reroute') return;
const const api: URLapi = new var URL: new (url: string | URL, base?: string | URL) => URLThe URL interface represents an object providing static methods used for creating object URLs.
URL class is a global reference for import { URL } from 'node:url'
https://nodejs.org/api/url.html#the-whatwg-url-api
URL('/api/reroute', url: anyurl);
const api: URLapi.URL.searchParams: URLSearchParamssearchParams.URLSearchParams.set(name: string, value: string): voidSets the value associated to a given search parameter to the given value. If there were several values, delete the others.
set('pathname', url: anyurl.pathname);
const const result: anyresult = await fetch: anyfetch(const api: URLapi).then(r: anyr => r: anyr.json());
return const result: anyresult.pathname;
}import type { type Reroute = (event: {
url: URL;
fetch: typeof fetch;
}) => MaybePromise<string | void>
The reroute hook allows you to modify the URL before it is used to determine which route to render.
Reroute } from '@sveltejs/kit';
export const const reroute: Reroutereroute: type Reroute = (event: {
url: URL;
fetch: typeof fetch;
}) => MaybePromise<string | void>
The reroute hook allows you to modify the URL before it is used to determine which route to render.
Reroute = async ({ url: URLurl, fetch: {
(input: RequestInfo | URL, init?: RequestInit): Promise<Response>;
(input: string | URL | globalThis.Request, init?: RequestInit): Promise<Response>;
}
fetch }) => {
// Ask a special endpoint within your app about the destination
if (url: URLurl.URL.pathname: stringpathname === '/api/reroute') return;
const const api: URLapi = new var URL: new (url: string | URL, base?: string | URL) => URLThe URL interface represents an object providing static methods used for creating object URLs.
URL class is a global reference for import { URL } from 'node:url'
https://nodejs.org/api/url.html#the-whatwg-url-api
URL('/api/reroute', url: URLurl);
const api: URLapi.URL.searchParams: URLSearchParamssearchParams.URLSearchParams.set(name: string, value: string): voidSets the value associated to a given search parameter to the given value. If there were several values, delete the others.
set('pathname', url: URLurl.URL.pathname: stringpathname);
const const result: anyresult = await fetch: (input: string | URL | globalThis.Request, init?: RequestInit) => Promise<Response> (+1 overload)fetch(const api: URLapi).Promise<Response>.then<any, never>(onfulfilled?: ((value: Response) => any) | null | undefined, onrejected?: ((reason: any) => PromiseLike<never>) | null | undefined): Promise<any>Attaches callbacks for the resolution and/or rejection of the Promise.
then(r: Responser => r: Responser.Body.json(): Promise<any>json());
return const result: anyresult.pathname;
};
rerouteis considered a pure, idempotent function. As such, it must always return the same output for the same input and not have side effects. Under these assumptions, SvelteKit caches the result ofrerouteon the client so it is only called once per unique URL.
transport
This is a collection of transporters, which allow you to pass custom types — returned from load and form actions — across the server/client boundary. Each transporter contains an encode function, which encodes values on the server (or returns a falsy value for anything that isn’t an instance of the type) and a corresponding decode function:
import { import VectorVector } 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: anyvalue) => value: anyvalue instanceof import VectorVector && [value: anyvalue.x, value: anyvalue.y],
decode: ([x, y]: [any, any]) => anydecode: ([x: anyx, y: anyy]) => new import VectorVector(x: anyx, y: anyy)
}
};import { import VectorVector } 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: Transporttransport: 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) => anyencode: (value: anyvalue) => value: anyvalue instanceof import VectorVector && [value: anyvalue.x, value: anyvalue.y],
Transporter<any, any>.decode: (data: any) => anydecode: ([x: anyx, y: anyy]) => new import VectorVector(x: anyx, y: anyy)
}
};