Hooks
Les “hooks” sont des fonctions que vous pouvez déclarer et que SvelteKit va appeler en réponse à des évènements spécifiques, vous permettant de contrôler finement le comportement de l’application.
Il y a trois fichiers de hooks, tous optionnels :
src/hooks.server.js— les hooks serveur de votre applicationsrc/hooks.client.js— les hooks client de votre applicationsrc/hooks.js— les hooks de votre application qui peuvent être exécutés à la fois sur le client et sur le serveur
Le code dans ces modules s’exécutera lors du démarrage de l’application, les rendant utile pour l’initialisation de clients de bases de données, parmi d’autres choses.
Vous pouvez configurer l’emplacement de ces fichiers avec
config.kit.files.hooks.
Hooks de serveur
Les hooks suivants peuvent être ajoutés au fichier src/hooks.server.js :
handle
Cette fonction est exécutée à chaque fois que le serveur SvelteKit reçoit une
requête — que cela se produise lors de l’exécution de
l’application ou lors du pré-rendu — et en détermine la
réponse. Elle reçoit un objet event représentant la requête
et une fonction appelée resolve, qui fait le rendu de la route et génère une Response. Ceci vous
permet de modifier les en-têtes ou body de réponse, ou de contourner complètement SvelteKit (pour
par exemple implémenter des routes programmatiquement).
/** @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('réponse personnalisée');
}
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('réponse personnalisée');
}
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;
};Les requêtes demandant des assets statiques — incluant les pages déjà prérendues — ne sont pas gérées par SvelteKit.
Si non implémentée, cette fonction vaut par défaut ({ event, resolve }) => resolve(event).
Durant le prérendu, Svelte parcourt vos pages à la recherche de liens et rend chaque route qu’il
trouve. Le fait de rendre la route provoque l’exécution de la fonction handle (et de toute autre
dépendance de route, comme load). Si vous avez besoin d’empêcher du code d’être exécuté lors de
cette phase, vérifier en amont que l’application n’est pas en train d’être compilée (via
building.
locals
Pour ajouter des données personnalisées à la requête, qui seront ensuite passées aux gestionnaires
des fichiers +server.js et aux fonctions load, remplissez l’objet event.locals, comme montré
ci-dessous.
/** @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);
// Notez que modifier les en-têtes de réponse n'est pas toujours sécurisé.
// Les objets de réponse peuvent avoir des en-têtes immutables (par ex.
// Response.redirect() renvoyé par un endpoint).
// Modifier les en-têtes immutables jette une erreur TypeError.
// Dans ce cas, clonez la réponse ou évitez de créer un objet de réponse
// ayant des en-têtes immutables.
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);
// Notez que modifier les en-têtes de réponse n'est pas toujours sécurisé.
// Les objets de réponse peuvent avoir des en-têtes immutables (par ex.
// Response.redirect() renvoyé par un endpoint).
// Modifier les en-têtes immutables jette une erreur TypeError.
// Dans ce cas, clonez la réponse ou évitez de créer un objet de réponse
// ayant des en-têtes immutables.
const response: Responseresponse.Response.headers: Headersheaders.Headers.set(name: string, value: string): voidset('x-custom-header', 'potato');
return const response: Responseresponse;
};Vous pouvez définir plusieurs fonctions handle et les exécuter avec la fonction utilitaire
sequence.
resolve supporte également un deuxième paramètre optionnel qui vous donne plus de contrôle sur la
manière dont la réponse va être rendue. Ce paramètre est un objet qui peut avoir les champs suivants
:
transformPageChunk(opts: { html: string, done: boolean }): MaybePromise<string | undefined>— applique des transformations personnalisées au HTML. Sidonevauttrue, il s’agit du dernier fragment. Il n’y a pas de garantie que chaque fragment individuel soit du HTML bien formé (il se peut qu’un fragment inclut la balise ouvrante d’un élément mais pas sa balise fermante, par exemple) mais ils seront toujours découpés à des endroits clés tels que%sveltekit.headou les composants de layout ou de page.filterSerializedResponseHeaders(name: string, value: string): boolean— détermine quels en-têtes devraient être inclus dans les réponses sérialisées lorsqu’une fonctionloadcharge une ressource avecfetch. Par défaut, aucun ne sera inclus.preload(input: { type: 'js' | 'css' | 'font' | 'asset', path: string }): boolean— détermine quels fichiers devraient être ajoutés à la balise<head>pour les précharger. La méthode est appelée avec chaque fichier trouvé pendant la construction des fragments de code au moment de la compilation — donc si vous avez par exempleimport './styles.css'dans votre fichier+page.svelte,preloadsera appelé avec le chemin résolu menant à ce fichier CSS lorsque la page sera visitée. Notez qu’en mode développementpreloadn’est pas appelé, puisqu’il dépend de l’analyse se produisant lors de la compilation. Le préchargement peut améliorer la performance en téléchargeant les assets plus tôt, mais cela peut aussi la pénaliser si trop de choses sont téléchargées sans raison. Par défaut, les fichiersjsetcssseront préchargés. Les fichiersassetne sont actuellement pas préchargés du tout, mais il est possible que cela soit ajouté à SvelteKit plus tard, en fonction des retours sur le sujet.
/** @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;
};Notez que resolve(...) ne lèvera jamais d’erreur, mais renverra toujours une Promise<Response>
avec le statut approprié. Si une erreur est levée ailleurs lors de l’exécution de handle, elle est
traitée comme étant fatale, et SvelteKit répondra avec une représentation JSON de l’erreur ou avec
la page d’erreur de secours — qui peut être personnalisée via src/error.html — selon la valeur de
l’en-tête Accept. Vous pouvez en apprendre plus à propos de la gestion des erreurs here.
handleFetch
Cette fonction vous permet de modifier (ou remplacer) le résultat d’un appel
event.fetch se produisant sur le serveur (ou pendant le pré-rendu)
au sein d’un endpoint, ou d’une fonction load, action, handle, handleError or reroute.
Par exemple, imaginons que votre fonction load fasse une requête vers une URL publique comme
https://api.yourapp.com lorsqu’un utilisateur ou utilisatrice effectue une navigation côté client
vers la page concernée. Lors du rendu serveur de cette page, cela aurait du sens d’appeler
directement l’API (en contournant tout éventuel proxy ou gestionnaire de charge qui pourrait se
trouver entre l’API et internet).
/** @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 la requête originale, mais change l'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 la requête originale, mais change l'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);
};Les requêtes faites avec event.fetch suivent le modèle d’authentification du navigateur — pour les
requêtes de même origine, les en-têtes cookie et authorization sont relayés à moins que l’option
credentials soit définie comme "omit". Pour les requêtes d’origine différente (cross-origin),
cookie sera inclus si l’URL de la requête appartient à un sous-domaine de l’application — par
exemple si votre appliation est sur my-domain.com et que votre API est sur api.my-domain.com,
les cookies seront inclus dans la requête.
Il y a tout de même une limitation : si votre application et votre API sont sur des sous-domaines
frères — www.my-domain.com et api.my-domain.com par exemple — alors un cookie appartenant à un
domaine parent commun comme my-domain.com ne sera pas inclus, car SvelteKit n’a aucun moyen de
savoir à quel domaine appartient le cookie. Dans ces situations vous devrez manuellement inclure le
cookie en utilisant handleFetch :
/** @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
Ce hook est appelé lorsqu’une fonction distante est appelée avec un argument qui ne correspond pas
au Standard Schema fourni. Il doit renvoyer un objet correspondant à
la forme de App.Error.
Si par exemple vous avez une fonction distante qui attend une chaîne de caractères comme 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) => {
// implémentation...
});... mais est exécutée avec quelque chose qui ne correspond pas au schéma — comme un nombre (par ex.
await getTodos(1)) — la validation va alors échouer, le serveur va répondre avec un code
400, et la fonction va jeter une erreur avec le message ‘Bad Request’.
Pour personnaliser ce message et ajouter des propriétés additionnelles à l’objet d’erreur,
implémentez handleValidationError :
/** @type {import('@sveltejs/kit').HandleValidationError} */
export function function handleValidationError({ issues }: {
issues: any;
}): {
message: string;
}
handleValidationError({ issues: anyissues }) {
return {
message: stringmessage: 'Non merci'
};
}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: 'Non merci'
};
};Soyez conscient•e des informations que vous exposez ici, car la raison d’échec de validation la plus probable est que quelqu’un de mal intentionné envoie des requêtes mal formées à votre serveur.
Hooks partagés
Vous pouvez ajouter les hooks suivants aux fichiers src/hooks.server.js et src/hooks.client.js
:
handleError
Si une erreur imprévue est levée lors du chargement, du rendu, ou de
l’exécution d’un endpoint, cette fonction sera exécutée avec les arguments error, event,
status et message. Cela permet deux choses :
- vous pouvez afficher l’erreur
- vous pouvez générer une représentation personnalisée de l’erreur que vous pouvez afficher aux
utilisateurs et utilisatrices, nettoyée des informations sensibles comme les messages ou les stack
traces. La valeur renvoyée, qui vaut par défaut
{ message }, devient la valeur de$page.error.
Pour les erreurs jetées depuis votre code (ou depuis du code d’une librairie appelée depuis votre
code), le statut sera 500 et le message sera “Internal Error”. Bien que error.message peut
contenir des informations sensibles qui ne devraient pas être exposées aux utilisateurs et
utilisatrices, message ne pose pas de problèmes (bien que sans grand intérêt pour une personne
lambda).
Pour ajouter plus d’informations à l’objet $page.error de manière typée, vous pouvez personnalisée
la forme attendue en déclarant une interface App.Error (qui doit inclure message: string, pour
garantir un comportement par défaut correct). Cela vous permet de — par exemple — ajouter un ID de
suivi que les utilisateurs et utilisatrices pourront utiliser comme référence lors de leurs échanges
potentiels avec vos équipes de support :
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();
// exemple d'intégration avec 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: 'Oups !',
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();
// exemple d'intégration avec 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: 'Oups !',
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();
// exemple d'intégration avec 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: 'Oups !',
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();
// exemple d'intégration avec 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: 'Oups !',
errorId: `${string}-${string}-${string}-${string}-${string}`errorId
};
};Dans le fichier
src/hooks.client.js, le type dehandleErrorestHandleClientErrorau lieu deHandleServerError, eteventest unNavigationEventplutôt qu’unRequestEvent.
Cette fonction n’est pas appelée pour les erreurs prévues (celles jetées depuis la fonction
error importée depuis @sveltejs/kit).
Lors du développement, si une erreur se produit à cause d’une erreur de syntaxe dans votre code
Svelte, l’erreur fournie aura une propriété frame mettant en valeur la position de l’erreur.
Assurez-vous que
handleErrorne jette jamais d’erreur.
init
Cette fonction est exécutée une seule fois, lorsque le serveur est créé ou lorsque l’application démarre dans le navigateur. C’est une fonction pratique pour effectuer des opérations asynchrones comme l’initialisation d’une connexion à une base de données.
Si votre environnement support le fait d’écrire
awaità la racine de votre fichier, utiliser la fonctioninitn’est pas vraiment différente d’initialiser votre logique d’initialisation à la racine du module, mais certains environnements — le plus connu étant Safari — ne le supportent pas.
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();
};Dans le navigateur, les tâches asynchrones au sein de
initvont retarder l’hydratation, soyez donc conscient•e de ce que vous y faites.
Hooks universels
Vous pouvez ajouter les fonctions suivantes au fichier src/hooks.js. Les hooks universels sont
exécutés à la fois sur le serveur et le client (à ne pas confondre avec les hooks partagés, qui sont
spécifiques à un environnement).
reroute
Cette fonction est exécutée avant handle et vous permet de changer la manière dont les URLs sont
traduites en routes. Le chemin renvoyé (qui vaut par défaut url.pathname) est utilisé pour
sélectionner la route et ses paramètres.
Par exemple, vous pourriez avoir une page src/routes/[[lang]]/about/+page.svelte, qui devrait être
accessible en tant que /en/about, /de/ueber-uns ou /fr/a-propos. Vous pourriez implémenter
ceci avec 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];
}
};Le paramètre lang sera correctement déduit du chemin renvoyé.
Le fait d’utiliser reroute ne changera pas le contenu de la barre d’adresse, ni la valeur de
event.url.
Depuis la version 2.18, le hook reroute peut être asynchrone, vous permettant de (par exemple)
récupérer des données depuis votre backend pour décider vers quelle route re-router. Assurez-vous
que la récupération de données soit rapide, car cela retardera la navigation sinon. Si vous avez
besoin de récupérer des données, utilisez la fonction fetch fourni en argument. Celle-ci hérite
des mêmes bénéfices que la fonction fetch fournie aux fonctions
load, avec l’inconvénient que params et id ne seront pas rendus disponibles pour
handleFetch car la route n’est à ce moment-là pas encore déterminée.
/** @type {import('@sveltejs/kit').Reroute} */
export async function function reroute({ url, fetch }: {
url: any;
fetch: any;
}): Promise<any>
reroute({ url: anyurl, fetch: anyfetch }) {
// Demandez à un endpoint spécial de votre application quelle est la 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 }) => {
// Demandez à un endpoint spécial de votre application quelle est la 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;
};La fonction
rerouteest considérée comme une fonction pure et idempotent. Par conséquence, elle doit toujours renvoyer le même résultat pour une entrée donnée, et ne doit pas avoir d’effets de bord. Avec ces considérations, SvelteKit va cacher le résultat dereroutesur le client afin quereroutene soit exécutée qu’une seule fois par URL unique.
transport
Une collection de transporteurs, qui vous permettent de fournir des types personnalisés — renvoyés
depuis une fonction load, au travers de la frontière serveur/client. Chaque transporteur contient
une fonction encode, qui encode les valeurs sur le serveur (ou renvoie une valeur falsy pour ce
qui n’est pas une instance du type) et une fonction decode correspondante :
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)
}
};Plus de lecture
Modifier cette page sur Github llms.txt