Concepts principaux
Options de page
Éditer cette page sur GithubPar défaut, SvelteKit va effectuer un rendu (ou un prérendu) de chaque composant d'abord sur le serveur, et l'envoyer au client en tant que HTML. Les composants seront rendus de nouveau dans le navigateur pour les rendre interactifs dans un processus appelé hydratation. Pour cette raison, vous devez vous assurez que vos composants puissent être exécutés dans les deux contextes. SvelteKit va ensuite initialiser un routeur qui prend la main sur les navigations suivantes.
Vous pouvez contrôler chacune de ces navigations, page par page, en exportant des options depuis +page.js
, depuis +page.server.js
, ou pour des groupes de pages depuis un +layout.js
ou un +layout.server.js
partagé. Pour définir une option s'appliquant à toute votre application, exportez la depuis le layout racine. Les layouts et pages enfantes écrasent les valeurs d'options définies dans les layouts parents, vous pouvez donc — par exemple — activer le prérendu pour toute votre application, la désactiver pour les pages qui ont besoin d'être rendues dynamiquement.
Vous pouvez définir ces options comme vous le souhaitez à différents endroits de votre application. Par exemple, vous pourriez prérendre votre page marketing pour optimiser la vitesse, faire un rendu serveur de vos pages dynamiques pour le référencement et l'accessibilité, et faire de vos pages d'administration une SPA en la rendant uniquement dans le navigateur. Cela fait de SvelteKit un outil très polyvalent.
prerenderpermalink
Il est probable qu'au moins quelques routes de votre application peuvent être représentées comme des simples fichiers HTML générés une fois pour toute à la compilation. Ces routes peuvent être prérendues.
ts
export constprerender = true;
ts
export constprerender = true;
Vous pouvez également définir export const prerender = true
dans votre +layout.js
ou votre +layout.server.js
racine, et prérendre toutes vos pages sauf celles explicitement définies comme à ne pas prérendre :
ts
export constprerender = false;
ts
export constprerender = false;
Les routes avec prerender = true
seront exclues des manifestes utilisés pour le SSR dynamique, vous permettant ainsi de réduire la taille de votre serveur (ou de vos fonctions serverless/edge). Dans certains cas vous pourriez avoir besoin de prérendre une route mais de tout de même l'inclure dans le manifeste (par exemple, avec une route comme /blog/[slug]
sur laquelle vous voulez prérendre votre contenu le plus récent ou le plus populaire, mais faire des rendus serveur pour le reste) — dans ces cas-là, il y a une troisième option, 'auto'
:
ts
export constprerender = 'auto';
ts
export constprerender = 'auto';
Si toute votre application est compatible pour du prérendu, vous pouvez utiliser l'adaptateur
adapter-static
, qui génèrera des fichiers que vous pourrez utiliser avec n'importe quel serveur web statique.
Le prérendu se fait en commençant par la racine de votre application et générer des fichiers pour toute page ou route +server.js
qu'il trouve. SvelteKit va chercher dans chaque page des éléments <a>
qui pointent vers d'autres pages potentiellement candidates au prérendu — grâce à ça, vous n'avez en général pas besoin de préciser quelles pages devraient être prérendues. Si vous avez besoin de préciser quelles pages devraient être accessibles par le générateur de prérendus, vous pouvez le faire avec config.kit.prerender.entries
, ou en exportant une fonction entries
de votre route dynamique.
Pendant le prérendu, la valeur de building
importé depuis $app/environment
sera true
.
Prérendu des routes de serveurpermalink
À la différence des autres options de page, prerender
s'applique aussi aux fichiers +server.js
. Ces fichiers ne sont pas affectés par les layouts, mais vont hériter des valeurs par défaut des pages qui les utilisent pour requêter leurs données, si elles existent. Par exemple, si un fichier +page.js
contient cette fonction load
...
ts
export constprerender = true;/** @type {import('./$types').PageLoad} */export async functionload ({fetch }) {constres = awaitfetch ('/my-server-route.json');return awaitres .json ();}
ts
import type {PageLoad } from './$types';export constprerender = true;export constload :PageLoad = async ({fetch }) => {constres = awaitfetch ('/my-server-route.json');return awaitres .json ();};
...alors src/routes/my-server-route.json/+server.js
sera prérendue, sauf si elle contient son propre export const prerender = false
.
Prérendu ou non ?permalink
La règle principale est la suivante : pour qu'une page puisse être prérendue, deux personnes arrivant dessus directement doivent voir le même contenu arriver du serveur.
Toutes les pages ne sont pas adaptées au prérendu. Tout contenu qui est prérendu sera affiché à tout le monde. Vous pouvez bien sûr requêter des données personnalisées dans une page prérendu en utilisant
onMount
, mais cela pourrait déboucher sur une plus mauvaise expérience utilisateur puisque du contenu vide ou de chargement sera affiché.
Notez que vous pouvez toujours prérendre des pages qui chargent des données en fonction des paramètres de page, comme cette route src/routes/blog/[slug]/+page.svelte
.
L'accès à url.searchParams
durant le prérendu est interdit. Si vous en avez besoin, assurez-vous que vous vous en servez uniquement dans le navigateur (par exemple dans onMount
).
Les pages avec des actions de formulaire ne peuvent pas être prérendues, car un serveur est nécessaire pour gérer les requêtes POST
des actions.
Conflits de routepermalink
Puisque le prérendu écrit dans votre système de fichiers, il n'est pas possible d'avoir deux endpoints qui génèreraient un dossier et un fichier avec le même nom. Par exemple, src/routes/foo/+server.js
et src/routes/foo/bar/+server.js
vont essayer de créer foo
et foo/bar
, ce qui n'est pas possible.
C'est entre autres pour cette raison qu'il est recommandé de toujours inclure une extension de fichier — src/routes/foo.json/+server.js
et src/routes/foo/bar.json/+server.js
vont générer des fichiers foo.json
et foo/bar.json
ayant le droit de vivre côte-à-côte.
Pour les pages, le problème ne se pose pas car SvelteKit écrit des fichiers foo/index.html
plutôt que foo
.
Résolution de problèmespermalink
Si vous rencontrez une erreur qui dit "The following routes were marked as prerenderable, but were not prerendered" ("Les routes suivantes ont été définies comme candidates au prérendu, mais n'ont pas été prérendues"), c'est parce que la route en question (ou un layout parent si c'est une page) a l'option export const prerender = true
, mais la page n'a pas été prérendue, parce que elle n'a pas pu être atteinte par le moteur de prérendu.
Puisque ces routes ne peuvent pas être rendues dynamiquement sur le serveur, cela va générer des erreurs pour les gens qui essaieront d'accéder à la route en question. Il y a deux moyens de régler ce problème :
- Assurez-vous que SvelteKit peut trouver la route via des liens en partant de
config.kit.prerender.entries
ou l'option de pageentries
. Ajoutez à cette option des liens aux routes dynamiques (i.e. les pages avec[parameters]
) si elles ne sont pas découvertes par le moteur via d'autres points d'entrée, sinon elles ne seront pas prérendues car SvelteKit ne sait pas quelle valeur le paramètre doit avoir. Les pages non définies comme candidates au prérendu seront ignorées et leur liens vers d'autres pages ne seront pas utilisées pour trouver d'autres pages, même si potentiellement d'autres seraient concernées. - Utilisez
export const prerender = 'auto'
plutôt queexport const prerender = true
. Les routes avec'auto'
peuvent être dynamiquement rendues sur le serveur.
entriespermalink
SvelteKit va découvrir les pages à prérendre automatiquement, en commençant par les points d'entrée et en les parcourant. Par défaut, toutes vos routes non dynamiques sont considérées comme des points d'entrées — par exemple, si vous avez ces routes...
/ # non dynamique
/blog # non dynamique
/blog/[slug] # dynamique, à cause de `[slug]`
...SvelteKit va prérendre /
et /blog
, et dans le même temps découvrir des liens comme <a href="/blog/hello-world">
qui lui donnent de nouvelles pages à prérendre.
La plupart du temps, c'est suffisant. Parfois, les liens vers des pages comme /blog/hello-world
peuvent ne pas exister (ou peuvent ne pas exister sur des pages prérendues), et dans ce cas il est nécessaire d'informer SvelteKit de leur existence.
Nous pouvons faire cela avec config.kit.prerender.entries
, ou en exportant une fonction entries
depuis un fichier +page.js
, +page.server.js
ou +server.js
appartenant à une route dynamique :
ts
/** @type {import('./$types').EntryGenerator} */export functionentries () {return [{slug : 'hello-world' },{slug : 'another-blog-post' }];}export constprerender = true;
ts
import type {EntryGenerator } from './$types';export constentries :EntryGenerator = () => {return [{slug : 'hello-world' }, {slug : 'another-blog-post' }];};export constprerender = true;
Vous pouvez définir la fonction entries
comme étant async
, vous permettant ainsi (par exemple) de récupérer une liste d'articles depuis un CMS ou une base de données.
ssrpermalink
Normalement, SvelteKit construit votre page d'abord sur le serveur, et envoie son HTML au client où il sera hydraté. Si vous définissez ssr
à false
, le serveur va plutôt construire une page "vide". C'est utile si votre page est incapable d'être rendue sur le serveur (parce que vous utilisez des variables globales uniquement définies dans le navigateur comme document
par exemple), mais dans la plupart des situations ce n'est pas recommandé (voir l'annexe).
ts
export constssr = false;// Si à la fois `ssr` et `csr` sont `false`, rien ne sera construit !
ts
export constssr = false;// Si à la fois `ssr` et `csr` sont `false`, rien ne sera construit !
Si vous ajoutez export const ssr = false
à votre fichier +layout.js
racine, toute votre application sera uniquement rendue sur le client — ce qui signifie que votre application devient une SPA.
csrpermalink
Ordinairement, SvelteKit hydrate votre HTML construit côté serveur en une page rendue sur le client ("client-side rendering" ou CSR). Certaines pages n'ont pas du tout besoin de JavaScript — la plupart des articles de blog et des pages "à propos" sont dans ce cas. Vous pouvez alors désactiver le CSR :
ts
export constcsr = false;// Si à la fois `ssr` et `csr` sont `false`, rien ne sera construit !
ts
export constcsr = false;// Si à la fois `ssr` et `csr` sont `false`, rien ne sera construit !
La désactivation du CSR implique qu'aucun JavaScript ne sera envoyé au client. Cela signifie :
- La page web doit être fonctionnelle avec uniquement du HTML et du CSS.
- Les balises
<script>
de tous les composants Svelte sont supprimées. - Les éléments
<form>
ne peuvent pas être améliorés progressivement. - Les liens sont gérés par le navigateur et entraînent une réactualisation complète de la page.
trailingSlashpermalink
Par défaut, SvelteKit va retirer les trailing slashs de vos URLs — si vous allez sur /about/
, il va répondre avec une redirection vers /about
. Vous pouvez changer de comportement avec l'option trailingSlash
, qui peut avoir comme valeur 'never'
(par défaut), 'always'
ou 'ignore'
.
Comme pour les autres options de page, vous pouvez exporter cette valeur d'un fichier +layout.js
ou +layout.server.js
, et elle s'appliquera à toutes les pages enfantes. Vous pouvez aussi exporter cette option depuis des fichiers +server.js
.
ts
export consttrailingSlash = 'always';
ts
export consttrailingSlash = 'always';
Cette option impacte aussi le prérendu. Si trailingSlash
vaut always
, une route comme /about
va générer un fichier about/index.html
, sinon elle génèrera un fichier about.html
, reflétant les conventions des serveurs web statiques.
Ignorer les trailing slashs n'est pas recommandé — la sémantique des chemins relatifs diffère alors entre les deux cas (
./y
depuis/x
est/y
, mais depuis/x/
c'est/x/y
), et/x
et/x/
seront traitées comme des URLs différentes, ce qui pénalise le référencement.
configpermalink
Avec le concept d'adaptateurs, SvelteKit est capable d'être exécuté sur différentes plateformes. Chacune peut avoir besoin d'une configuration spécifique pour déclencher le déploiement — par exemple, sur Vercel vous pouvez choisir de déployer certaines parties de votre application sur le réseau edge et d'autres sur des environnement serverless.
config
est un objet avec des paires clé-valeur à sa racine. À part cette contrainte, sa forme précise dépend de l'adaptateur que vous utilisez. Chaque adaptateur devrait vous fournir une interface Config
à importer pour vous fournir du typage. Consultez la documentation de votre adaptateur pour plus d'informations.
ts
/** @type {import('some-adapter').Config} */export constconfig = {runtime : 'edge'};
ts
import type {Config } from 'some-adapter';export constconfig :Config = {runtime : 'edge',};
Les objets config
sont fusionnés à la racine de votre application (mais pas dans les niveaux plus profonds). Cela signifie que vous n'avez pas besoin de répéter toutes les valeurs dans un fichier +page.js
si vous souhaitez uniquement écraser certaines valeurs de la configuration définie dans +layout.js
. Par exemple, cette configuration de layout...
ts
export constconfig = {runtime : 'edge',regions : 'all',foo : {bar : true}}
ts
export constconfig = {runtime : 'edge',regions : 'all',foo : {bar : true,},};
...est écrasée par cette configuration de page...
ts
export constconfig = {regions : ['us1', 'us2'],foo : {baz : true}}
ts
export constconfig = {regions : ['us1', 'us2'],foo : {baz : true,},};
...qui résulte de cette valeur de configuration { runtime: 'edge', regions: ['us1', 'us2'], foo: { baz: true } }
pour cette page.