Cours Svelte et SvelteKit · Module 11: Routage SvelteKit
Pages d'erreur et pages spéciales
Dans cette leçon4
+error.svelte
<!-- src/routes/+error.svelte -->
<script>
import { page } from '$app/state';
</script>
<h1>Erreur {page.status}</h1>
<p>{page.error?.message}</p>
<a href="/">Retour à la page d'accueil</a>L'objet page de $app/state est réactif et tu le lis sans signe $. L'ancien store $page du module $app/stores a été supprimé dans SvelteKit 3.
Signaler des erreurs
// src/routes/warriors/[id]/+page.js
import { error } from '@sveltejs/kit';
export function load({ params }) {
const warrior = getWarrior(params.id);
if (!warrior) {
error(404, 'Guerrier introuvable');
}
return { warrior };
}La fonction error() lève l'exception elle-même : tu n'écris donc pas throw devant (c'était la forme de SvelteKit 1). Le deuxième argument est toujours le texte du message.
+page.js vs +page.server.js
// +page.js - s'exécute sur le serveur ET le client
export function load({ params, fetch }) {
// Peut être appelé pendant la navigation côté client
return { data };
}// +page.server.js - serveur UNIQUEMENT
export function load({ params, locals }) {
// Accès à la base de données, aux secrets, etc.
return { data };
}Redirections
import { redirect } from '@sveltejs/kit';
export function load({ locals }) {
if (!locals.user) {
redirect(303, '/login');
}
return { user: locals.user };
}Comme error(), la fonction redirect() lève l'exception elle-même, sans throw.
Code de cette leçon : App.svelte
<script>
// Navigation programmatique et états de chargement
let loading = $state(false);
let currentPage = $state('home');
async function navigateTo(page) {
loading = true;
// Simulation du chargement des données
await new Promise(r => setTimeout(r, 1000));
currentPage = page;
loading = false;
}
// Simulation de beforeNavigate
function handleBeforeNavigate(e, page) {
if (currentPage === 'form' && !confirm('Quitter la page ?')) {
e.preventDefault();
return;
}
navigateTo(page);
}
</script>
<main class="navigation-demo">
<h1>Navigation SvelteKit</h1>
<nav class="nav">
<button onclick={(e) => handleBeforeNavigate(e, 'home')}>Accueil</button>
<button onclick={(e) => handleBeforeNavigate(e, 'warriors')}>Guerriers</button>
<button onclick={(e) => handleBeforeNavigate(e, 'form')}>Formulaire</button>
</nav>
{#if loading}
<div class="loading">
<div class="spinner"></div>
<p>Chargement...</p>
</div>
{:else}
<section class="content">
{#if currentPage === 'home'}
<h2>Page d’accueil</h2>
<p>Bienvenue dans l’appli !</p>
{:else if currentPage === 'warriors'}
<h2>Guerriers</h2>
<p>Liste chargée depuis le serveur</p>
{:else if currentPage === 'form'}
<h2>Formulaire</h2>
<p>Quitter entraînera une perte de données !</p>
<input placeholder="Écris quelque chose..." />
{/if}
</section>
{/if}
<section class="code-example">
<h2>Navigation programmatique</h2>
<pre>
import {"{"} goto {"}"} from '$app/navigation';
// Navigation simple
goto('/warriors');
// Avec options
goto('/warriors', {"{"}
replace: true,
refreshAll: true
{"}"});
</pre>
</section>
</main>
<style>
.navigation-demo {
font-family: 'Georgia', serif;
max-width: 600px;
margin: 0 auto;
padding: 2rem;
background: #0a1628;
color: #b8d4f7;
min-height: 100vh;
}
h1 {
color: #4a90d9;
text-align: center;
}
.nav {
display: flex;
justify-content: center;
gap: 0.5rem;
margin-bottom: 2rem;
}
button {
padding: 0.75rem 1.5rem;
background: #1e3a5f;
color: #b8d4f7;
border: 1px solid #4a90d9;
border-radius: 4px;
cursor: pointer;
}
button:hover {
background: #2a4a6f;
}
.loading {
text-align: center;
padding: 3rem;
}
.spinner {
width: 50px;
height: 50px;
border: 4px solid #1e3a5f;
border-top-color: #4a90d9;
border-radius: 50%;
animation: spin 1s linear infinite;
margin: 0 auto 1rem;
}
@keyframes spin {
to { transform: rotate(360deg); }
}
section {
background: rgba(74, 144, 217, 0.1);
border: 1px solid #4a90d9;
border-radius: 8px;
padding: 1rem;
margin: 1rem 0;
}
h2 {
color: #4a90d9;
margin-top: 0;
}
input {
width: 100%;
padding: 0.75rem;
background: rgba(0,0,0,0.3);
border: 1px solid #4a90d9;
border-radius: 4px;
color: #b8d4f7;
margin-top: 0.5rem;
}
pre {
background: rgba(0,0,0,0.5);
padding: 1rem;
border-radius: 4px;
font-size: 0.85rem;
overflow-x: auto;
}
</style>Entrées de la documentation utilisées dans cette leçon
Tu as repéré une erreur dans cette leçon ?
Teste tes connaissances
Réponds aux questions de cette leçon. Choisis une réponse pour voir tout de suite si elle est correcte.
1. Comment signaler une erreur 404 dans la fonction load (SvelteKit 3) ?