Au coeur de SvelteKit se trouve un _routeur basé sur le système de fichiers_. Les routes de votre application — c-à-d les chemins d'URL auquels les utilisateurs et utilisatrices peuvent accéder — sont définis par les dossiers de votre projet : - `src/routes` est la route racine - `src/routes/about` crée une route `/about` - `src/routes/blog/[slug]` crée une route avec un _paramètre_, `slug`, qui peut être utilisé pour charger des données de manière dynamique lorsqu'un utilisateur ou utilisatrice requête une page comme `/blog/hello-world` > [!NOTE] Vous pouvez changer `src/routes` pour utiliser un dossier différent en modifiant la > [configuration de votre projet](configuration). Chaque dossier de route contient un ou plusieurs _fichiers de route_, qui sont identifiables à leur préfixe `+`. Nous présenterons bientôt ces fichiers dans le détail, mais voici déjà quelques règles simples pour vous aider à vous souvenir comment le routing de SvelteKit fonctionne : * Tous les fichiers peuvent être exécutés sur le serveur * Tous les fichiers peuvent être exécutés côté client, sauf les fichiers `+server` * Les fichiers `+layout` et `+error` s'appliquent au dossier dans lequel ils sont définis, ainsi qu'à tous les sous-dossiers de ce dossier ## +page ### +page.svelte Un composant `+page.svelte` définit une page de votre application. Par défaut, les pages sont rendues à la fois sur le serveur ([SSR](glossary#SSR)) pour la requête initiale, et dans le navigateur ([CSR](glossary#CSR)) pour les navigations suivantes. ```svelte

Bonjour et bienvenue sur mon site !

À propose de mon site ``` ```svelte

À propos de ce site

TODO...

Accueil ``` > [!NOTE] SvelteKit utilise les éléments `` pour naviguer entre les routes, plutôt qu'un > composant spécifique au framework, comme `` par exemple. Les pages peuvent recevoir des données des fonctions `load` via la prop `data`. ```svelte

{data.title}

{@html data.content}
``` > [!LEGACY] > `PageProps` a été ajouté dans la version 2.16.0 de SvelteKit. Dans les versions antérieures, vous > deviez typer les propriétés `data` manuellement avec `PageData`, voir [$types](#\$types). > > En Svelte 4, vous deviez utiliser `export let data`. ### +page.js Souvent, une page a besoin de charger des données avant de pouvoir être rendue. Pour cela, nous pouvons ajouter un module `+page.js` qui exporte une fonction `load` : ```js /// file: src/routes/blog/[slug]/+page.js import { error } from '@sveltejs/kit'; /** @type {import('./$types').PageLoad} */ export function load({ params }) { if (params.slug === 'hello-world') { return { title: 'Bonjour tout le monde !', content: 'Bienvenue sur notre blog. Lorem ipsum dolor sit amet...' }; } error(404, 'Not found'); } ``` Cette fonction est exécutée avec `+page.svelte`, ce qui signifie qu'elle est exécutée lors du rendu côté serveur, et dans le navigateur lors de la navigation côté client. Voir [`load`](load) pour plus de détails sur l'API. En plus de `load`, `+page.js` peut exporter des valeurs qui configurent le comportement de la page : - `export const prerender = true` ou `false` ou `'auto'` - `export const ssr = true` ou `false` - `export const csr = true` ou `false` Vous pouvez trouver plus d'informations sur ces options dans le chapitre [Options de page](page-options). ### +page.server.js Si votre fonction `load` ne peut pas être exécutée ailleurs que sur le serveur — par exemple, si elle a besoin de récupérer des données depuis une base de données ou si vous avez besoin de lire des [variables d'environnement privées]($env-static-private) comme des clés d'API — vous pouvez alors renommer `+page.js` en `+page.server.js` et changer le type de `PageLoad` en `PageServerLoad`. ```js /// file: src/routes/blog/[slug]/+page.server.js // @filename: ambient.d.ts declare global { const getPostFromDatabase: (slug: string) => { title: string; content: string; } } export {}; // @filename: index.js // ---cut--- import { error } from '@sveltejs/kit'; /** @type {import('./$types').PageServerLoad} */ export async function load({ params }) { const post = await getPostFromDatabase(params.slug); if (post) { return post; } error(404, 'Not found'); } ``` Lors de la navigation côté client, SvelteKit va charger ces données sur le serveur, ce qui signifie que la valeur renvoyée doit être sérialisable par [devalue](https://github.com/rich-harris/devalue). Voir le chapitre [`load`](load) pour plus de détails sur l'API. Comme `+page.js`, `+page.server.js` peut exporter des [options de page](page-options) — `prerender`, `ssr` et `csr`. Un fichier `+page.server.js` peut également exporter des _actions_. Si `load` vous permet de lire des données sur le serveur, `actions` vous permet d'écrire des données _sur_ le serveur en utilisant l'élément `
`. Pour apprendre comment vous en servir, voir la section sur les [actions de formulaire](form-actions). ## +error Si une erreur se produit pendant l'exécution de `load`, SvelteKit va rendre une page d'erreur par défaut. Vous pouvez personnaliser cette page d'erreur route par route en ajoutant un fichier `+error.svelte` : ```svelte

{page.status}: {page.error.message}

``` > [!LEGACY] > `$app/state` a été ajouté dans la version 2.12 de SvelteKit. Si vous utilisez une version plus > ancienne ou si vous utilisez Svelte 4, utilisez plutôt `$app/stores`. SvelteKit va "remonter à la racine" à la recherche de la frontière d'erreur la plus proche — si le fichier dans l'exemple ci-dessus n'existait pas, il essaierait `src/routes/blog/+error.svelte`, puis `src/routes/+error.svelte` avant de rendre la page d'erreur par défaut. Si _ceci_ échoue (ou si l'erreur a été levée depuis la fonction `load` du `+layout` racine, qui est conceptuellement "au-dessus" du fichier `+error` racine), SvelteKit va sauver les meubles et rendre une page d'erreur statique de secours, que vous pouvez personnaliser en créant un fichier `src/error.html`. Si l'erreur se produit dans une fonction `load` d'un `+layout(.server).js`, la frontière d'erreur la plus proche dans l'arbre est un fichier `+error.svelte` "au-dessus" de ce layout (et non au même "endroit"). Si aucune route ne peut être trouvée (404), le fichier `src/routes/+error.svelte` (ou la page d'erreur par défaut si ce fichier n'existe pas), sera utilisé. > [!NOTE] `+error.svelte` n'est _pas_ utilisé lorsqu'une erreur se produit au sein de > ['handle'](hooks#Server-hooks-handle) ou d'un gestionnaire de requête [+server.js](#server). Vous pouvez en apprendre plus sur la gestion des erreurs [ici](errors). ## +layout Jusqu'à maintenant, nous avons traité les pages comme des composants autonomes — lors d'une navigation, le composant `+page.svelte` existant est détruit, et un nouveau vient le remplacer. Mais dans beaucoup d'applications, certains éléments doivent être visibles sur _chaque_ page, comme par exemple les éléments principaux de navigation ou un pied-de-page. Plutôt que les répéter dans chaque fichier `+page.svelte`, nous pouvons les mettre dans des _layouts_. ### +layout.svelte Pour créer un layout qui s'applique à toutes les pages, créez un fichier appelé `src/routes/+layout.svelte`. Le layout par défaut (celui que SvelteKit utilise si vous n'en créez pas un vous-même) ressemble à ça... ```svelte {@render children()} ``` ... mais nous pouvons ajouter n'importe quel markup, style, ou comportement. Le chose requise est que le composant doit inclure une balise `@render` pour afficher le contenu de la page. Par exemple, ajoutons une barre de navigation : ```svelte
{@render children()} ``` Si nous créons les pages correspondant à `/`, `/about` et `/settings`... ```html /// file: src/routes/+page.svelte

Accueil

``` ```html /// file: src/routes/about/+page.svelte

À propos

``` ```html /// file: src/routes/settings/+page.svelte

Paramètres

``` ... la barre de navigation sera toujours visible, et la navigation entre ces trois pages ne va se traduire uniquement par le remplacement du `

`. Les layouts peuvent être _imbriqués_. Supposez que n'ayons pas une seule page `/settings`, mais plutôt des pages imbriquées comme `/settings/profiles` et `/settings/notifications` avec un sous-menu commun (vous pouvez retrouver un exemple de la vraie vie sur la page [github.com/settings](https://github.com/settings)). Nous pouvons créer un layout qui s'applique uniquement aux pages sous la route `/settings` (tout en héritant du layout racine qui contient la barre de navigation principale) : ```svelte

Settings

{@render children()} ``` > [!LEGACY] > `LayoutProps` a été ajouté dans la version 2.16.0 de SvelteKit. Dans les versions antérieures, > vous deviez [typer les propriétés manuellement](#\$types). Vous pouvez maintenant constater la manière dont `data` est remplie en inspectant l'exemple de `+layout.js` de la prochaine section, juste en-dessous. Par défaut, chaque layout hérite du layout au-dessus de lui. Parfois ce n'est pas ce que souhaitez — dans ce cas, les [layouts avancés](advanced-routing#Advanced-layouts) peuvent être utiles. ### +layout.js Tout comme `+page.svelte` vient charger ses données de `+page.js`, un composant `+layout.svelte` peut charger ses données depuis la fonction [`load`](load) d'un `+layout.js`. ```js /// file: src/routes/settings/+layout.js /** @type {import('./$types').LayoutLoad} */ export function load() { return { sections: [ { slug: 'profile', title: 'Profil' }, { slug: 'notifications', title: 'Notifications' } ] }; } ``` Si un fichier `+layout.js` exporte des [options de pages](page-options) — `prerender`, `ssr` et `csr` — ces options seront utilisées comme valeurs par défaut pour les pages enfant. Les données renvoyées par la fonction `load` d'un layout sont également disponibles pour toutes ses pages enfant : ```svelte ``` > [!NOTE] Souvent, les données de layout ne changent pas lors de la navigation entre pages. > SvelteKit ré-exécute intelligemment les fonctions [`load`](load) uniquement lorsque c'est > nécessaire. ### +layout.server.js Pour exécuter sur le serveur la fonction `load` de votre layout, déplacez-la dans un fichier `+layout.server.js`, et changer le type `LayoutLoad` en `LayoutServerLoad`. Comme `+layout.js`, `+layout.server.js` peut exporter des [options de page](page-options) — `prerender`, `ssr` et `csr`. ## +server Comme pour les pages, vous pouvez définir des routes avec un fichier `+server.js` (parfois appelé "route d'API" ou "endpoint"), ce qui vous donne un contrôle total sur la réponse. Votre fichier `+server.js` exporte des fonctions correspondant aux verbes HTTP comme `GET`, `POST`, `PATCH`, `PUT`, `DELETE`, `OPTIONS`, et `HEAD` qui prennent en argument un [`RequestEvent`](@sveltejs-kit#RequestEvent) et renvoient un objet [`Response`](https://developer.mozilla.org/en-US/docs/Web/API/Response). Par exemple, nous pourrions créer une route `/api/random-number` avec un gestionnaire `GET` : ```js /// file: src/routes/api/random-number/+server.js import { error } from '@sveltejs/kit'; /** @type {import('./$types').RequestHandler} */ export function GET({ url }) { const min = Number(url.searchParams.get('min') ?? '0'); const max = Number(url.searchParams.get('max') ?? '1'); const d = max - min; if (isNaN(d) || d < 0) { error(400, 'min et max doivent être des nombres, et min doit être plus petit que max'); } const random = min + Math.random() * d; return new Response(String(random)); } ``` Le premier argument à `Response` peut être un [`ReadableStream`](https://developer.mozilla.org/en-US/docs/Web/API/ReadableStream), rendant possible le streaming de grandes quantité de données ou bien la création d'évènements envoyés par le serveur (à moins que vous déployiez sur des plateformes qui transforment les réponses en buffers, comme AWS Lambda). Vous pouvez utiliser les méthodes [`error`](@sveltejs-kit#error), [`redirect`](@sveltejs-kit#redirect), et [`json`](@sveltejs-kit#json) de `@sveltejs/kit` pour des raisons pratiques (mais leur usage n'est pas nécessaire). Si une erreur est jetée (soit avec `error(...)`, soit par un évènement inattendu), la réponse sera une représentation JSON de l'erreur ou la page d'erreur de secours — qui peut être personnalisée via `src/error.html` — en fonction de l'en-tête `Accept`. Le composant [`+error.svelte`](#error) ne sera _pas_ rendu dans ce cas. Vous pouvez en savoir plus sur la gestion des erreurs [ici](errors). > [!NOTE] Lorsque vous créez un gestionnaire `OPTIONS`, notez que Vite va injecter les en-têtes > `Acces-Control-Allow-Origin` et `Access-Control-Allow-Methods` — ceux-ci ne seront présents en > production à moins que vous les y ajoutiez. > [!NOTE] Les fichiers `+layout` n'ont aucun effet sur les fichiers `+server.js`. Si vous souhaitez > exécuter de la logique avant chaque requête, ajoutez-la dans le hook serveur > [`handle`](hooks#Server-hooks-handle). ### Recevoir des données [!VO]Receiving data En exportant des gestionnaires `POST`/`PUT`/`PATCH`/`DELETE`/`OPTIONS`/`HEAD`, les fichiers `+server.js` peuvent être utilisés pour créer une API complète : ```svelte + = {total} ``` ```js /// file: src/routes/api/add/+server.js import { json } from '@sveltejs/kit'; /** @type {import('./$types').RequestHandler} */ export async function POST({ request }) { const { a, b } = await request.json(); return json(a + b); } ``` > [!NOTE] En général, les [actions de formulaire](form-actions) sont une meilleure manière de > soumettre des données du navigateur vers le serveur. > [!NOTE] Si un gestionnaire `GET` est exporté, une requête `HEAD` renverra la donnée > `content-length` du body de réponse du gestionnaire `GET`. ### Gestionnaire de méthode de secours [!VO]Fallback method handler Exporter le gestionnaire `fallback` va matcher toute requête correspondant à une méthode non gérée, y compris les méthodes comme `MOVE` qui n'ont pas d'export dédié prévu par `+server.js`. ```js /// file: src/routes/api/add/+server.js import { json, text } from '@sveltejs/kit'; /** @type {import('./$types').RequestHandler} */ export async function POST({ request }) { const { a, b } = await request.json(); return json(a + b); } // Ce gestionnaire va répondre à PUT, PATCH, DELETE, etc. /** @type {import('./$types').RequestHandler} */ export async function fallback({ request }) { return text(`J'ai attrapé votre requête ${request.method} !`); } ``` > [!NOTE] Pour les requêtes `HEAD`, le gestionnaire `GET` est prioritaire sur le gestionnaire > `fallback`. ### Négociation de contenu [!VO]Content negotiation Les fichiers `+server.js` peuvent être placés dans le même dossier que les fichiers `+page`, permettant à la même route d'être soit une page, soit un endpoint d'API. Pour les distinguer, SvelteKit applique les règles suivantes : - Les requêtes `PUT`/`PATCH`/`DELETE`/`OPTIONS` sont toujours gérées par `+server.js` puisque ces méthodes ne s'appliquent pas aux pages - Les requêtes `GET`/`POST`/`HEAD` sont traitées comme des requêtes de page si l'en-tête `accept` priorise `text/html` (en d'autres mots, si la requête vient d'une page ouverte par un navigateur), sinon elles seront traitées par `+server.js`. - Les réponses aux requêtes `GET` inclueront un en-tête `Vary: Accept`, de sorte que les proxies et les navigateurs puissent cacher les réponses HTML et JSON séparément. ## $types Dans les exemples ci-dessus, nous avons importé les types depuis un fichier `$types.d.ts`. Il s'agit d'un fichier que SvelteKit crée pour vous dans un dossier caché si vous utilisez TypeScript (ou JavaScript avec les annotations de type JSDoc) afin de vous fournir du typage lorsque vous travaillez sur vos fichiers de routes. Par exemple, annoter `let { data } = $props()` avec `PageProps` (ou `LayoutProps`, pour un fichier `+layout.svelte`) indique à TypeScript que le type de `data` est défini par le type de retour de la fonction `load` correspondante : ```svelte ``` > [!NOTE] > Les types `PageProps` et `LayoutProps`, ajoutés dans la version 2.16.0, sont un raccourci de > typer la prop `data` en tant que `PageData` ou `LayoutData`, ainsi que pour d'autres props, comme > `form` pour les pages, ou `children` pour les layouts. Dans des versions antérieures, vous deviez > typer ces propriétés manuellement. Par exemple, pour une page : > > ```js > /// file: +page.svelte > /** @type {{ data: import('./$types').PageData, form: import('./$types').ActionData }} */ > let { data, form } = $props(); > ``` > > Ou, pour un layout : > > ```js > /// file: +layout.svelte > /** @type {{ data: import('./$types').LayoutData, children: Snippet }} */ > let { data, children } = $props(); > ``` De plus, annoter la fonction `load` avec `PageLoad`, `PageServerLoad`, `LayoutLoad`, ou `LayoutServerLoad` (pour respectivement `+page.js`, `+page.server.js`, `+layout.js` ou `+layout.server.js`) permet de s'assurer que `params` et la valeur de retour sont correctement typées. Si vous utilisez VS Code ou tout IDE supportant le protocole LSP (Language Server Protocol) et les plugins TypeScript, vous pouvez omettre ces types _complètement_ ! L'outillage d'IDE de Svelte va insérer les types adéquats à votre place, afin de profiter du typage des données de page et de layout sans que ayez à l'écrire vous-même. Cela fonctionne également au sein de notre outil en ligne de commande `svelte-check`. Vous pouvez en apprendre plus sur le fait d'omettre `$types` dans notre [article de blog](/blog/zero-config-type-safety) dédié. ## Autres fichiers [!VO]Other files Tout autre fichier dans un dossier de route est ignoré par SvelteKit. Ceci signifie que vous pouvez ranger des composants et autres modules utilitaires dans les dossiers des routes qui les nécessitent. Si des composants ou modules sont requis par plusieurs routes, c'est une bonne idée de les mettre dans le dossier [`$lib`]($lib). ## En savoir plus [!VO]Further reading - [Tutoriel : Routing](/tutorial/kit/pages) - [Tutoriel : Routes d'API](/tutorial/kit/get-handlers) - [Docs : Routing avancé](advanced-routing)