Skip to main content

Référencement

L’aspect le plus important du référencement (SEO] est la création de contenu de qualité largement cité par d’autres ressources sur le web. Toutefois, il y a quelques considérations techniques permettant de créer des sites qui performent bien à ce niveau.

Clé-en-main

SSR

Même si les moteurs de recherche se sont améliorés depuis quelques années dans l’indexation de contenu rendu avec du code JavaScript côté client, le contenu rendu sur le serveur est indexé plus souvent et plus efficacement. SvelteKit utilise le SSR par défaut, et bien que vous puissiez le désactiver dans le hook handle, vous devriez le laisser activé à moins que n’ayez une bonne raison de ne pas le faire.

Le rendu de SvelteKit est très configurable et vous pouvez implémenter du rendu dynamique si nécessaire. Ce n’est généralement pas recommandé, puisque le SSR offre d’autres avantages que le référencement.

Performance

Des indicateurs comme les Core Web Vitals impactent le classment d’une page par les moteurs de recherche. Puisque Svelte et SvelteKit introduisent une surcouche minimale, il est plus facile de créer des sites de haute performance. Vous pouvez tester les performances de votre site en utilisant les outils de Google PageSpeed Insights ou Lighthouse. Lisez la page sur les performances pour plus de détails.

URLs normalisées

SvelteKit redirige les chemins ayant des trailing slashes vers des chemins n’en ayant pas (ou inversement selon votre configuration), car les URLs dupliquées détériorent le référencement.

Mise en place manuelle

<title> et <meta>

Chaque page devrait avoir des éléments <title> et <meta name="description"> uniques et bien écrits dans un élément <svelte:head>. Des conseils sur comment écrire des titres et descriptions pertinentes, en plus d’autres suggestions sur comment rendre votre contenu compréhensible par les moteurs de recherche, sont disponibles dans la documentation Lighthouse SEO audits.

Un usage commun est de renvoyer les data concernant le référencement depuis vos fonctions load, puis de les utiliser (en tant que page.data) dans l’élément <svelte:head> de votre layout racine.

Sitemaps

src/routes/sitemap.xml/+server
export async function function GET(): Promise<Response>GET() {
	return new var Response: new (body?: BodyInit | null, init?: ResponseInit) => Response

This Fetch API interface represents the response to a request.

MDN Reference

Response
(
` <?xml version="1.0" encoding="UTF-8" ?> <urlset xmlns="https://www.sitemaps.org/schemas/sitemap/0.9" xmlns:xhtml="https://www.w3.org/1999/xhtml" xmlns:mobile="https://www.google.com/schemas/sitemap-mobile/1.0" xmlns:news="https://www.google.com/schemas/sitemap-news/0.9" xmlns:image="https://www.google.com/schemas/sitemap-image/1.1" xmlns:video="https://www.google.com/schemas/sitemap-video/1.1" > <!-- les éléments <url> se déclarent ici --> </urlset>`.String.trim(): string

Removes the leading and trailing white space and line terminator characters from a string.

trim
(),
{ ResponseInit.headers?: HeadersInit | undefinedheaders: { 'Content-Type': 'application/xml' } } ); }

AMP

Une réalité malheureuse du développement web moderne est qu’il est quelques fois nécessaire de créer une version Accelerated Mobile Pages (AMP) de votre site. SvelteKit vous permet de le faire en définissant l’option inlineStyleThreshold...

svelte.config
/** @type {import('@sveltejs/kit').Config} */
const 
const config: {
    kit: {
        inlineStyleThreshold: number;
    };
}
@type{import('@sveltejs/kit').Config}
config
= {
kit: {
    inlineStyleThreshold: number;
}
kit
: {
// puisque <link rel="stylesheet"> n'est pas // autorisé, inliner tous les styles inlineStyleThreshold: numberinlineStyleThreshold: var Infinity: numberInfinity } }; export default
const config: {
    kit: {
        inlineStyleThreshold: number;
    };
}
@type{import('@sveltejs/kit').Config}
config
;

..., en désactivant l’option csr de vos fichiers +layout.js / +layout.server.js...

src/routes/+layout.server
export const const csr: falsecsr = false;

..., en ajoutant amp à votre fichier app.html...

<html amp>
...

..., et en transformant le HTML utilisant l’option transformPageChunk avec transform importé depuis @sveltejs/amp :

src/hooks.server
import * as import ampamp from '@sveltejs/amp';

/** @type {import('@sveltejs/kit').Handle} */
export async function 
function handle({ event, resolve }: {
    event: any;
    resolve: any;
}): Promise<any>
@type{import('@sveltejs/kit').Handle}
handle
({ event: anyevent, resolve: anyresolve }) {
let let buffer: stringbuffer = ''; return await resolve: anyresolve(event: anyevent, {
transformPageChunk: ({ html, done }: {
    html: any;
    done: any;
}) => string | undefined
transformPageChunk
: ({ html: anyhtml, done: anydone }) => {
let buffer: stringbuffer += html: anyhtml; if (done: anydone) return import ampamp.function transform(html: string): stringtransform(let buffer: stringbuffer); } }); }
import * as import ampamp from '@sveltejs/amp';
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<Partial<Record<string, string>>, string | null>event, resolve: (event: RequestEvent, opts?: ResolveOptions) => MaybePromise<Response>resolve }) => {
let let buffer: stringbuffer = ''; return await resolve: (event: RequestEvent, opts?: ResolveOptions) => MaybePromise<Response>resolve(event: RequestEvent<Partial<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.

@paraminput the html chunk and the info if this is the last chunk
transformPageChunk
: ({ html: stringhtml, done: booleandone }) => {
let buffer: stringbuffer += html: stringhtml; if (done: booleandone) return import ampamp.function transform(html: string): stringtransform(let buffer: stringbuffer); } }); };

To prevent shipping any unused CSS as a result of transforming the page to amp, we can use dropcss:

src/hooks.server
import * as import ampamp from '@sveltejs/amp';
import module "dropcss"dropcss from 'dropcss';

/** @type {import('@sveltejs/kit').Handle} */
export async function 
function handle(input: {
    event: RequestEvent;
    resolve: (event: RequestEvent, opts?: ResolveOptions) => MaybePromise<Response>;
}): MaybePromise<...>
@type{import('@sveltejs/kit').Handle}
handle
({ event: RequestEvent<Partial<Record<string, string>>, string | null>event, resolve: (event: RequestEvent, opts?: ResolveOptions) => MaybePromise<Response>resolve }) {
let let buffer: stringbuffer = ''; return await resolve: (event: RequestEvent, opts?: ResolveOptions) => MaybePromise<Response>resolve(event: RequestEvent<Partial<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.

@paraminput the html chunk and the info if this is the last chunk
transformPageChunk
: ({ html: stringhtml, done: booleandone }) => {
let buffer: stringbuffer += html: stringhtml; if (done: booleandone) { let let css: stringcss = ''; const const markup: stringmarkup = import ampamp .function transform(html: string): stringtransform(let buffer: stringbuffer) .String.replace(searchValue: string | RegExp, replaceValue: string): string (+3 overloads)

Replaces text in a string, using a regular expression or search string.

@paramsearchValue A string or regular expression to search for.
@paramreplaceValue A string containing the text to replace. When the {@linkcode searchValue} is a RegExp, all matches are replaced if the g flag is set (or only those matches at the beginning, if the y flag is also present). Otherwise, only the first match of {@linkcode searchValue} is replaced.
replace
('⚡', 'amp') // dropcss ne peut pas gérer ce caractère
.
String.replace(searchValue: {
    [Symbol.replace](string: string, replacer: (substring: string, ...args: any[]) => string): string;
}, replacer: (substring: string, ...args: any[]) => string): string (+3 overloads)

Replaces text in a string, using an object that supports replacement within a string.

@paramsearchValue A object can search for and replace matches within a string.
@paramreplacer A function that returns the replacement text.
replace
(/<style amp-custom([^>]*?)>([^]+?)<\/style>/, (match: stringmatch, attributes: anyattributes, contents: anycontents) => {
let css: stringcss = contents: anycontents; return `<style amp-custom${attributes: anyattributes}></style>`; }); let css: stringcss = module "dropcss"dropcss({ css: stringcss, html: stringhtml: const markup: stringmarkup }).css; return const markup: stringmarkup.String.replace(searchValue: string | RegExp, replaceValue: string): string (+3 overloads)

Replaces text in a string, using a regular expression or search string.

@paramsearchValue A string or regular expression to search for.
@paramreplaceValue A string containing the text to replace. When the {@linkcode searchValue} is a RegExp, all matches are replaced if the g flag is set (or only those matches at the beginning, if the y flag is also present). Otherwise, only the first match of {@linkcode searchValue} is replaced.
replace
('</style>', `${let css: stringcss}</style>`);
} } }); }
import * as import ampamp from '@sveltejs/amp';
import module "dropcss"dropcss from 'dropcss';
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<Partial<Record<string, string>>, string | null>event, resolve: (event: RequestEvent, opts?: ResolveOptions) => MaybePromise<Response>resolve }) => {
let let buffer: stringbuffer = ''; return await resolve: (event: RequestEvent, opts?: ResolveOptions) => MaybePromise<Response>resolve(event: RequestEvent<Partial<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.

@paraminput the html chunk and the info if this is the last chunk
transformPageChunk
: ({ html: stringhtml, done: booleandone }) => {
let buffer: stringbuffer += html: stringhtml; if (done: booleandone) { let let css: stringcss = ''; const const markup: stringmarkup = import ampamp .function transform(html: string): stringtransform(let buffer: stringbuffer) .String.replace(searchValue: string | RegExp, replaceValue: string): string (+3 overloads)

Replaces text in a string, using a regular expression or search string.

@paramsearchValue A string or regular expression to search for.
@paramreplaceValue A string containing the text to replace. When the {@linkcode searchValue} is a RegExp, all matches are replaced if the g flag is set (or only those matches at the beginning, if the y flag is also present). Otherwise, only the first match of {@linkcode searchValue} is replaced.
replace
('⚡', 'amp') // dropcss ne peut pas gérer ce caractère
.
String.replace(searchValue: {
    [Symbol.replace](string: string, replacer: (substring: string, ...args: any[]) => string): string;
}, replacer: (substring: string, ...args: any[]) => string): string (+3 overloads)

Replaces text in a string, using an object that supports replacement within a string.

@paramsearchValue A object can search for and replace matches within a string.
@paramreplacer A function that returns the replacement text.
replace
(/<style amp-custom([^>]*?)>([^]+?)<\/style>/, (match: stringmatch, attributes: anyattributes, contents: anycontents) => {
let css: stringcss = contents: anycontents; return `<style amp-custom${attributes: anyattributes}></style>`; }); let css: stringcss = module "dropcss"dropcss({ css: stringcss, html: stringhtml: const markup: stringmarkup }).css; return const markup: stringmarkup.String.replace(searchValue: string | RegExp, replaceValue: string): string (+3 overloads)

Replaces text in a string, using a regular expression or search string.

@paramsearchValue A string or regular expression to search for.
@paramreplaceValue A string containing the text to replace. When the {@linkcode searchValue} is a RegExp, all matches are replaced if the g flag is set (or only those matches at the beginning, if the y flag is also present). Otherwise, only the first match of {@linkcode searchValue} is replaced.
replace
('</style>', `${let css: stringcss}</style>`);
} } }); };

C’est une bonne idée d’utiliser le hook handle pour valider le HTML transformé en utilisant amphtml-validator, mais uniquement si vous pré-rendez vos pages, car ce traitement est très lent.

Modifier cette page sur Github llms.txt