Options de page
Par défaut, SvelteKit va rendre (ou pré-rendre) tout composant d’abord sur le serveur puis l’envoyer au client en tant que HTML. Le composant sera ensuite rendu de nouveau dans le navigateur pour le rendre interactif dans un processus appelée hydratation. Pour cette raison, vous devez vous assurer que les composants puissent être exécutés à la fois sur le serveur et dans le navigateur. Puis Sveltekit initialisera un routeur côté client qui va prendre le relais pour toutes les navigations à venir.
Vous pouvez contrôler chacune de ces étapes page par page en exportant des options depuis les
fichiers +page.js
ou +page.server.js
, ou
pour des groupes de page en exportant ces options depuis un fichier
+layout.js
ou +layout.server.js
partagé par les pages concernées. Pour définir une option pour toute l’application, exportez-la
depuis le layout racine. Les layouts enfants et les pages surchargent les valeurs des options
définies dans des layouts parents, ce qui veut dire que, — par exemple — vous pouvez activer le
pré-rendu pour toute votre application puis le désactiver pour les pages qui ont besoin d’être
rendues dynamiquement.
Vous pouvez mélanger ces options à différents endroits de votre application. Par exemple, vous pourriez pré-rendre votre page marketing pour optimiser sa vitesse d’affichage, rendre sur le serveur vos pages dynamiques pour en optimiser le référencement et l’accessibilité, et faire de votre section d’administration une SPA en la rendant uniquement côté client. Tout cela rend SvelteKit très versatile.
prerender
Il est probable qu’au moins quelques unes des routes de votre application puisse être représentées comme un simple fichier HTML généré au moment de la compilation. Ces routes peuvent être pré-rendues.
export const const prerender: true
prerender = true;
Vous pouvez également définir export const prerender = true
dans votre fichier +layout.js
ou
ou +layout.server.js
racine, et pré-rendre toute votres application à l’exception des pages
qui se définissent explicitement comme ne devant pas être pré-rendues :
export const const prerender: false
prerender = false;
Les routes avec prerender = true
seront exclues des manifestes utilisés pour le rendu côté serveur
(SSR) dynamique, diminuant le poids de votre serveur (ou de vos fonctions serverless/edge). Dans
certains cas, vous pourriez vouloir pré-rendre une route mais également l’inclure dans le manifeste
(par exemple, avec une route comme /blog/[slug]
, dont vous souhaitez pré-rendre le contenu le plus
populaire/récent mais rendre sur le serveur le reste) — pour ces situations, il existe une
troisième option, 'auto'
:
export const const prerender: "auto"
prerender = 'auto';
Si toute votre application est compatible avec le pré-rendu, vous pouvez utiliser l’adaptateur
adapter-static
, qui va générer des fichiers pouvant être utilisés avec n’importe quel serveur web statique.
Le processus de pré-rendu commence à la racine de votre application et génère des fichiers pour
toutes les pages ou routes +server.js
pouvant être pré-rendues qu’il trouve. Chaque page est
scannée à la recherche d’éléments <a>
pointant vers d’autres pages candidates au pré-rendu — pour
cette raison, vous n’avez pas besoin de préciser quelles pages doivent être accessibles au processus
de pré-rendu. Si vous devez préciser les pages devant être accessibles au processus de pré-rendu,
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ée depuis $app/environment
sera true
.
Pré-rendu des routes de serveur
À 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 hériteront des valeurs par défaut de
l’option des pages qui leur demandent des données, s’il en existe. Par exemple, si un fichier
+page.js
contient cette fonction load
...
export const const prerender: true
prerender = true;
/** @type {import('./$types').PageLoad} */
export async function function load({ fetch }: {
fetch: any;
}): Promise<any>
load({ fetch: any
fetch }) {
const const res: any
res = await fetch: any
fetch('/my-server-route.json');
return await const res: any
res.json();
}
import type { type PageLoad = (event: Kit.LoadEvent<Record<string, any>, Record<string, any> | null, Record<string, any>, string | null>) => MaybePromise<void | Record<string, any>>
type PageLoad = (event: Kit.LoadEvent<Record<string, any>, Record<string, any> | null, Record<string, any>, string | null>) => MaybePromise<void | Record<string, any>>
PageLoad } from './$types';
export const const prerender: true
prerender = true;
export const const load: PageLoad
load: type PageLoad = (event: Kit.LoadEvent<Record<string, any>, Record<string, any> | null, Record<string, any>, string | null>) => MaybePromise<void | Record<string, any>>
type PageLoad = (event: Kit.LoadEvent<Record<string, any>, Record<string, any> | null, Record<string, any>, string | null>) => MaybePromise<void | Record<string, any>>
PageLoad = async ({ fetch: {
(input: RequestInfo | URL, init?: RequestInit): Promise<Response>;
(input: string | URL | globalThis.Request, init?: RequestInit): Promise<Response>;
}
fetch
is equivalent to the native fetch
web API, with a few additional features:
- It can be used to make credentialed requests on the server, as it inherits the
cookie
and authorization
headers for the page request.
- It can make relative requests on the server (ordinarily,
fetch
requires a URL with an origin when used in a server context).
- Internal requests (e.g. for
+server.js
routes) go directly to the handler function when running on the server, without the overhead of an HTTP call.
- During server-side rendering, the response will be captured and inlined into the rendered HTML by hooking into the
text
and json
methods of the Response
object. Note that headers will not be serialized, unless explicitly included via filterSerializedResponseHeaders
- During hydration, the response will be read from the HTML, guaranteeing consistency and preventing an additional network request.
You can learn more about making credentialed requests with cookies here
fetch }) => {
const const res: Response
res = await fetch: (input: string | URL | globalThis.Request, init?: RequestInit) => Promise<Response> (+1 overload)
fetch('/my-server-route.json');
return await const res: Response
res.Body.json(): Promise<any>
json();
};
... alors le fichier src/routes/my-server-route.json/+server.js
sera traité comme candidat au
pré-rendu s’il ne contient pas son propre export const prerender = false
.
Quand ne pas pré-rendre
La règle d’or est la suivante : pour qu’une page puisse être pré-rendue, deux personnes arrivant directement sur cette page doivent obtenir le même contenu du serveur.
Toutes les pages ne sont pas compatibles avec le pré-rendu. Tout contenu qui est pré-rendu sera vu par toutes les utilisateurs et utilisatrices. Vous pouvez bien sûr récupérer des données personnalisées via
onMount
dans une page pré-rendue, mais cela peut se traduire en une moins bonne expérience utilisateur, puisque cela implique d’afficher initialement un contenu vide ou des indicateurs de chargement.
Notez que vous pouvez toujours pré-rendre des pages qui chargent leurs données en fonction des
paramètres de page, comme sur une route src/routes/blog/[slug]/+page.svelte
.
Lire url.searchParams
pendant le pré-rendu est interdit. Si vous devez
vous en servir, assurez-vous que vous le faites uniquement dans le navigateur (par exemple avec
onMount
).
Les pages comportant des actions ne peuvent pas être prérendues, car un serveur doit
être capable de gérer les requêtes POST
venant de l’action.
Conflits de route
Puisque le pré-rendu écrit dans le 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 est impossible.
Pour cette raison parmi d’autres, 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 créer des fichiers
foo.json
et foo/bar.json
qui peut coexister en harmonie côte-à-côte.
Pour les pages, nous contournons ce problème en écrivant foo/index.html
au lieu de foo
.
Résolution de problèmes
Si vous rencontrez une erreur comme ‘The following routes were marked as prerenderable, but were not
prerendered’ (“Les routes suivantes ont été marquées comme devant être
pré-rendues, mais n’ont pas été pré-rendues”), c’est parce que la route en question (ou
éventuellement un layout parent, si c’est une page) a l’option export const prerender = true
mais
la page n’a pas été atteinte par le processus de pré-rendu, et n’a donc pas été pré-rendue.
Puisque ces routes ne peuvent pas être dynamiquement rendues sur le serveur, ceci va causer des erreurs pour les personnes qui essaieraient d’accéder à la route en question. Il y a quelques moyens de régler ce problème :
- Assurez-vous que SvelteKit peut trouver la route en suivant des liens depuis
les entrées précisées dans
config.kit.prerender.entries
ou dans l’option de pageentries
. Ajoutez des liens aux routes dynamiques (c-à-d les pages avec des[parameters]
) à cette option si celles-ci ne sont pas trouvables en passant par les autres point d’entrée, sans quoi elles ne seront pas pré-rendues car SvelteKit ne peut pas savoir quelles valeurs les paramètres peuvent avoir. Les pages non marquées comme pouvant être pré-rendues seront ignorées et leurs liens vers d’autres pages ne seront pas utilisés lors du processus de pré-rendu, même si certaines d’entre elles pourraient être pré-rendues. - Assurez-vous que SvelteKit peut trouver la route en découvrant un lien la ciblant depuis l’une des autres pages pré-rendues ayant du rendu côté serveur activé.
- Changez
export const prerender = true
enexport const prerender = 'auto'
. Les routes avec'auto'
peuvent être dynamiquement rendues sur le serveur.
entries
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ée — par exemple, si vous avez ces routes...
/ # non dynamique
/blog# non dynamique
/blog/[slug] # dynamique, à cause de `[slug]`
... SvelteKit va prérendre /
and /blog
, et au cours du processus découvrir des liens comme <a href="/blog/hello-world>
, lui donnant de nouvelles pages à pré-rendre.
La plupart du temps, c’est suffisant. Dans certaines situations, les liens vers des pages comme
/blog/hello-world
peuvent ne pas exister (ou peuvent ne pas exister sur des pages pré-rendues),
auquel cas il est nécessaire de déclarer à SvelteKit leur existence.
Vous pouvez 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 :
/** @type {import('./$types').EntryGenerator} */
export function function entries(): {
slug: string;
}[]
entries() {
return [
{ slug: string
slug: 'hello-world' },
{ slug: string
slug: 'another-blog-post' }
];
}
export const const prerender: true
prerender = true;
import type { type EntryGenerator = () => Promise<Array<Record<string, any>>> | Array<Record<string, any>>
type EntryGenerator = () => Promise<Array<Record<string, any>>> | Array<Record<string, any>>
EntryGenerator } from './$types';
export const const entries: EntryGenerator
entries: type EntryGenerator = () => Promise<Array<Record<string, any>>> | Array<Record<string, any>>
type EntryGenerator = () => Promise<Array<Record<string, any>>> | Array<Record<string, any>>
EntryGenerator = () => {
return [
{ slug: string
slug: 'hello-world' },
{ slug: string
slug: 'another-blog-post' }
];
};
export const const prerender: true
prerender = true;
entries
peut être une fonction async
, vous permettant (par exemple) de récupérer une liste
d’articles depuis un CMS ou une base de données, dans l’exemple ci-dessus.
ssr
Normalement, SvelteKit rend votre page d’abord sur le serveur, puis envoie le HTML construit vers le
client où celui-ci va être hydraté. Si vous définissez ssr
à false
, la
page construite par le serveur sera alors une “coquille” vide. C’est utile si votre page ne peut pas
être rendue sur le serveur (parce que vous utilisez des variables globales comme document
par
exemple), mais dans la plupart des situations, ce n’est pas recommandé (voir les
annexes).
export const const ssr: false
ssr = false;
// Si à la `ssr` et `csr` sont `false`, rien ne sera affiché !
Si vous ajoutez export const ssr = false
à votre fichier +layout.js
racine, votre application
toute entière sera uniquement rendue sur le client — ce qui signifie que votre application devient
une SPA.
Si toutes vos options de page sont des valeurs booléenes ou des chaînes de caractères litérales, SvelteKit va les évaluer de manière statique. Sinon, il va importer votre fichier
+page.js
ou+layout.js
sur le serveur (à la fois lors de compilation et à l’exécution si votre application n’est pas complètement statique) afin d’en évaluer les options. Dans le deuxième cas, du code exclusif au navigateur ne doit pas être exécuté lorsque le module se charge. En pratique, ceci signifie que vous devriez plutôt importer votre code exclusif au navigateur dans votre fichier+page.svelte
ou+layout.svelte
.
csr
D’ordinaire, SvelteKit hydrate votre HTML rendu sur le serveur (SSR) en une page interactive rendue sur le client (CSR). Certaines pages ne nécessitent pas du tout JavaScript — la plupart des articles de blog et des pages “à propos” tombent dans cette catégorie. Dans ces cas-là vous pouvez désactiver le CSR.
export const const csr: false
csr = false;
// Si à la `ssr` et `csr` sont `false`, rien ne sera affiché !
Désactiver le CSR permet de ne pas envoyer de JavaScript au client. Cela signifie :
- La page web doit pouvoir fonctionner avec uniquement du HTML et du CSS.
- Les balises
<script>
au sein des composants Svelte vont être supprimées. - Les éléments
<form>
ne peuvent pas être améliorés progressivement. - Les liens sont gérés par le navigateur et génèrent un rechargement complet de la page lors des navigations.
- Le remplacement instantané de modules (Hot Module Replacement, ou HMR) est désactivé.
Vous pouvez activer le csr
pendant le développement (par exemple pour tirer profit du HMR) de
cette manière :
import { const dev: boolean
Whether the dev server is running. This is not guaranteed to correspond to NODE_ENV
or MODE
.
dev } from '$app/environment';
export const const csr: boolean
csr = const dev: boolean
Whether the dev server is running. This is not guaranteed to correspond to NODE_ENV
or MODE
.
dev;
trailingSlash
Par défaut, SvelteKit va supprimer les slashs à la fin des URLs — si vous allez sur /about
,
SvelteKit va répondre avec une redirection vers /about
. Vous pouvez changer ce comportement avec
l’option trailingSlash
, qui peut avoir comme valeur 'never'
(valeur par défaut), 'always'
, ou
'ignore'
.
Comme avec les autres options de page, vous pouvez exporter cette valeur depuis un fichier
+layout.js
ou +layout.server.js
, et celle-ci s’appliquera alors à toutes les pages enfant. Vous
pouvez aussi exporter la configuration depuis des fichiers +server.ts
.
export const const trailingSlash: "always"
trailingSlash = 'always';
Cette option affecte aussi le pré-rendu. Si trailingSlash
vaut 'always'
, une route
comme /about
va générer un fichier about/index.html
, sinon le fichier généré sera about.html
,
comme recommandé par les conventions de serveur web statiques.
Il n’est pas recommandé d’ignorer les slashs de fin d’URLs — la sémantique des chemins relatifs diffère entre les 2 situations (
./y
depuis/x
est/y
, mais depuis/x/
c’est/x/y
), et/x
et/x/
sont traités comme des URLs différentes, ce qui pénalise le référencement.
config
Avec le concept d’adaptateurs, SvelteKit est capable de tourner sur une grande variété de plateformes. Chacune d’entre elles peut avoir une configuration spécifique permettant de modifier le déploiement — par exemple sur Vercel vous pourriez choisir de déployer certaines parties de votre application sur l’edge et d’autres sur des environnements serverless.
config
est un objet de paires clé-valeur à la racine. À part ça, sa forme dépend de l’adaptateur
que vous utilisez. Chaque adaptateur devrait fournir une interface Config
à importer pour fournir
le typage adapté. Consultez la documentation de votre adaptateur pour plus d’informations.
/** @type {import('some-adapter').Config} */
export const const config: Config
config = {
Config.runtime: string
runtime: 'edge'
};
import type { Config } from 'some-adapter';
export const const config: Config
config: Config = {
Config.runtime: string
runtime: 'edge'
};
Les objets config
sont fusionnés au premier niveau (mais pas plus profond). Ceci signifie que
vous n’avez pas besoin de répéter toutes les valeurs dans un fichier +page.js
si vous souhaitez
uniquement surcharger quelques unes des valeurs définies dans un fichier +layout.js
. Par exemple,
cette configuration de layout...
export const const config: {
runtime: string;
regions: string;
foo: {
bar: boolean;
};
}
config = {
runtime: string
runtime: 'edge',
regions: string
regions: 'all',
foo: {
bar: boolean;
}
foo: {
bar: boolean
bar: true
}
}
... est surchargée par cette configuration de page...
export const const config: {
regions: string[];
foo: {
baz: boolean;
};
}
config = {
regions: string[]
regions: ['us1', 'us2'],
foo: {
baz: boolean;
}
foo: {
baz: boolean
baz: true
}
}
... ce qui résulte dans la valeur de configuration { runtime: 'edge', regions: ['us1', 'us2'], foo: { baz: true } }
pour cette page.
Plus de lecture
Modifier cette page sur Github llms.txt