Guide SvelteKit Deployment SEO: Adapters, Prerendering, et Edge Rendu

SvelteKit's adapter et per-route prerender paramètres decide où et quand votre pages rendre — et que drives TTFB, LCP, et budget d’exploration. A deployment-focused deep dive: choosing adapter-static/node/vercel/cloudflare/netlify, prerender = vrai/faux/'auto', edge-runtime constraints, et building sitemap.xml et robots.txt.

Première publication : 3 juil. 2026 · Dernière mise à jour : 3 août 2026 · Avancé

SvelteKit's adapter et per-route prerender paramètre decide où et quand une page renders — static HTML à construire temps, SSR on a serveur, or SSR à le edge — et que décision drives TTFB, qui feeds LCP et explorer capacity. Pick adapter-static pour pure contenu sites, a node/vercel/cloudflare adapter avec per-route prerender pour mixed contenu-plus-app sites, et an edge adapter quand mondial TTFB matters (accepting cold commence et aucun Node fs). prerender = 'auto' est le mixed-site outil. Edge runtimes ne peut pas lire le filesystem. Et SvelteKit generates aucun sitemap.xml or robots.txt — vous construire ceux as +serveur.js endpoints, avec le stratégie selon votre adapter.

TL;DR — Le adapter ne fait pas modifier ce que SvelteKit renders — il changements où et quand: construire-time static (adapter-static), requête-time on a serveur vous exécuter (adapter-node), or requête-time on serverless/edge functions (adapter-vercel/-netlify/-cloudflare). Per-route prerender = true construit static HTML et drops le route depuis le dynamic manifest; prerender = 'auto' prerenders et garde il dans le manifest — le outil pour mixed /blog/[slug] sites. Edge runtimes exécuter on V8 isolates: aucun Node fs, et cold commence hurt TTFB, qui feeds LCP et (per Google’s explorer-budget doc) explorer capacity. SvelteKit generates aucun sitemap.xml or robots.txt — construire les as +server.js endpoints, et remarque le stratégie dépend on le adapter. Ce est a narrower, deployment-focused companion à le SvelteKit SEO fundamentals article dans ce section; Je assume vous déjà know SvelteKit est SSR-par-default et ne va pas re-litigate que ici.

The un idea que rend tout of ce click

Le adapter fait pas modifier ce que renders. Il changements où et quand. c’est le entier chose. Le SvelteKit docs put il precisely: adapters “prendre le construit app as entrée et generate sortie pour deployment.” Preuve à l’appui de cette affirmation SvelteKit adapters take the built application as input and generate deployment-specific output. Portée : Deployment output; adapter choice can still constrain supported runtime features. Niveau de confiance : élevé · Vérifié : SvelteKit: Adapters Votre components, votre load functions, votre <svelte:head> metadata — identical à travers chaque adapter. Ce que differs est:

  • Quand le HTML est produced: à construire temps (static/prerendered) or à requête temps (SSR on a serveur, serverless function, or edge function).
  • Où c’est produced: on a unique origin serveur, on a regional serverless function, or on an edge network fermer à le visitor.

Everything ci-dessous is a consequence of ceux two axes.

Pourquoi deployment choices sont SEO choices

Le chain est court et well-documented: TTFB → LCP → explorer capacity.

Temps à premier byte est comment long le host takes à commencer sending la réponse. A prerendered fichier servi depuis a CDN cache a a near-zero TTFB. A serveur que a à rendre lune page a a plus élevé un. A cold-starting serverless or edge function peut ont a beaucoup plus élevé un on le premier hit. TTFB est a direct entrée à Largest Contentful Paint — vous pouvez’t paint ce que vous haven’t reçu — et LCP est a Core Web Vitals signal.

«The crawl side is where Google is most explicit. From the crawl-budget documentation: “If the site responds quickly for a while, the limit goes up, meaning more connections can be used to crawl. If the site slows down or responds with server errors, the limit goes down and Google crawls less.” And the best-practice line: “Make your pages efficient to load. If Google can load and render your pages faster, we might be able to read more content from your site.” A cold-starting edge function that’s slow to respond is subject to the same dynamic as a slow origin server. » (Traduction) (Résumé en français de la section vingt-six, sous-partie un : le texte source est conservé pour vérification lors de la relecture francophone.)

«One honesty note up front: Google publishes no SvelteKit-specific guidance. There’s no doc or Search Off the Record episode naming SvelteKit adapters, prerender = 'auto', or edge cold starts. What I’m doing here is applying Google’s general rendering and crawl-budget guidance to SvelteKit’s specific mechanics — not quoting a rep who commented on SvelteKit, because none has. The Google framing that “server-side or pre-rendering is still a great idea because it makes your website faster for users and crawlers, and not all bots can run JavaScript” is the closest official anchor, and it’s framework-agnostic. » (Traduction) (Résumé en français de la section vingt-sept, sous-partie un : le texte source est conservé pour vérification lors de la relecture francophone.)

«## Choosing an adapter for SEO outcomes » (Traduction) (Résumé en français de la section vingt-huit, sous-partie un : le texte source est conservé pour vérification lors de la relecture francophone.)

«### adapter-auto — the zero-config default, and its ceiling » (Traduction) (Résumé en français de la section vingt-neuf, sous-partie un : le texte source est conservé pour vérification lors de la relecture francophone.)

«New SvelteKit projects ship with adapter-auto. It detects the platform — Vercel, Netlify, Cloudflare Pages, Azure, AWS — and installs the matching adapter at build time. It’s a fine starting point, but there’s a hard ceiling worth knowing: adapter-auto does not take any options. The moment you need { edge: true }, Cloudflare bindings, Vercel ISR, or any platform-specific configuration, you install the underlying adapter (adapter-vercel, adapter-cloudflare, etc.) directly. Treat auto as a scaffold, not a production decision. » (Traduction) (Résumé en français de la section trente, sous-partie un : le texte source est conservé pour vérification lors de la relecture francophone.)

«### adapter-static — full SSG, for content-first sites » (Traduction) (Résumé en français de la section trente et un, sous-partie un : le texte source est conservé pour vérification lors de la relecture francophone.)

«adapter-static prerenders your whole site to static files at build time. No server runs; a host serves flat HTML. Preuve à l’appui de cette affirmation adapter-static prerenders a SvelteKit site as static files. Portée : Routes must be prerenderable; performance outcomes depend on hosting and page design. Niveau de confiance : élevé · Vérifié : SvelteKit: Static site generation For a content-first site this is the strongest SEO profile you can have — lowest TTFB, no cold starts, nothing to fall over. The one requirement is the trap covered at length in the fundamentals article: SSR must stay on during the build, or you get empty shells instead of rendered HTML. I won’t re-explain that here beyond flagging it. » (Traduction) (Résumé en français de la section trente-deux, sous-partie un : le texte source est conservé pour vérification lors de la relecture francophone.)

«The catch is rigidity. Anything that genuinely needs server logic per request (true search, per-user content, form handling without a third-party endpoint) can’t live on a purely static build — which is exactly what the next adapters are for. » (Traduction) (Résumé en français de la section trente-trois, sous-partie un : le texte source est conservé pour vérification lors de la relecture francophone.)

«### adapter-node — a server you control » (Traduction) (Résumé en français de la section trente-quatre, sous-partie un : le texte source est conservé pour vérification lors de la relecture francophone.)

«adapter-node produces a standalone Node.js server. You run it, you scale it, you own the TTFB. This is the most flexible option and the one with the fewest runtime surprises — full Node APIs, including fs. It’s a good fit when you have infrastructure already, need Node libraries that edge runtimes can’t run, or want predictable (non-cold-starting) response times from a warm server. The tradeoff is operational: you’re running a server, and its speed and uptime are now your crawl capacity. » (Traduction) (Résumé en français de la section trente-cinq, sous-partie un : le texte source est conservé pour vérification lors de la relecture francophone.)

«### adapter-vercel — serverless, edge, and ISR » (Traduction) (Résumé en français de la section trente-six, sous-partie un : le texte source est conservé pour vérification lors de la relecture francophone.)

«adapter-vercel deploys to Vercel’s serverless functions by default, with several SEO-relevant levers set per route via export const config: » (Traduction) (Résumé en français de la section trente-sept, sous-partie un : le texte source est conservé pour vérification lors de la relecture francophone.)

  • runtime: 'edge' moves que route à Vercel’s edge runtime (plus ci-dessous).
  • regions contrôle où serverless functions exécuter — closer à votre utilisateurs (or votre database) signifie lower latency.
  • isr enables Incremental Static Regeneration: isr: { expiration: 60 } sert a mis en cache static asset et regenerates il après le window, giving “le performances et coût advantages de prerendered contenu avec le flexibility de dynamically rendu contenu.” ISR est a genuine fourth chemin entre pure-static et pure-SSR — mais remarque le docs’ propre caveat: “En utilisant ISR on a route avec export const prerender = true va ont aucun effect, since le route est prerendered à construire temps.” ISR et prerender sont alternatives, pas stackable.

adapter-cloudflare — Workers/Pages, global edge

adapter-cloudflare targets Cloudflare Workers et Pages — SSR on a mondial edge network, souvent le lowest TTFB pour a geographically spread public. Le important constraint est le runtime: Workers exécuter on V8 isolates, pas Node. Depuis le docs: “Vous ne peut pas utiliser fs dans Cloudflare Workers.” Some Node APIs fonctionner seulement behind le nodejs_compat compatibility flag, et même alors prise en charge n’est pas un-à-un. Si vous étaient reading fichiers à requête temps (a redirection map, a données fichier, custom OG-image inputs), que code nécessite a rethink — covered dans le edge section ci-dessous.

(Le older adapter-cloudflare-workers est deprecated; nouveau projects utiliser adapter-cloudflare, qui handles les deux Workers et Pages. Si vous êtes on le old un, migrating est le recommended chemin.)

«### adapter-netlify — functions or Edge Functions (Deno) » (Traduction) (Résumé en français de la section quarante-deux, sous-partie un : le texte source est conservé pour vérification lors de la relecture francophone.)

«adapter-netlify deploys to Netlify’s Node-based functions by default, or to Deno-based Edge Functions with edge: true. Same shape as Vercel: default serverless with an edge opt-in. One SvelteKit-specific footnote — Netlify Forms require the form’s page to be prerendered so Netlify can detect the form markup at deploy time, which is a small “prerender this route” requirement layered on top of the adapter choice. » (Traduction) (Résumé en français de la section quarante-trois, sous-partie un : le texte source est conservé pour vérification lors de la relecture francophone.)

La décision en une ligne chaque

  • Pure contenu site → adapter-static, prerender tout.
  • Contenu site avec dynamic pockets → adapter-node/-vercel/-cloudflare, prerender = true on contenu, false/'auto' on le dynamic routes.
  • App/dashboard avec personalization → SSR-premier (node or edge), prerender seulement le static shell (marketing, login).
  • Mondial, TTFB-critical public → an edge adapter pour le dynamic routes, accepting le Node-API constraints et cold-commencer reality.

(Le Arbre de décision tab walks ce as a branching flow.)

Prerendering strategy pour mixed sites

Ce que true / false / 'auto' en réalité do

export const prerender est a per-route (or per-layout) page option, et le three valeurs ne sont pas simplement on/off:

  • true — construire ce route à static HTML à construire temps. Critically, c’est “excluded depuis manifests utilisé pour dynamic SSR, making votre serveur (or serverless/edge functions) plus petit.” Une fois prerendered, le route ne peut pas fall back à dynamic rendu — c’est static, complet arrêter.
  • false — toujours rendre on requête. Aucun static fichier.
  • 'auto' — le mixed-site outil. Il prerenders le route et garde il dans le dynamic serveur manifest, donc le même route peut être servi statically pour connu paths et serveur-rendu pour le rest. Ce est construit pour exactly le cas le docs décrire: a route comme /blog/[slug] “où vous vouloir à prerender votre la plupart recent/popular contenu mais serveur-rendre le long tail.”

Parce que prerendered routes shrink le serveur bundle, a mostly-prerendered site with a few 'auto'/false routes deploys a plus petit, cheaper, faster function — an efficiency win independent of SEO.

Dynamic routes besoin an entries function

Le prerender robot d’exploration discovers pages par suivant <a> liens depuis votre entry points. Que fonctionne pour static routes, mais a dynamic route comme /blog/[slug] a aucun fixed URL pour le robot d’exploration à trouver. Si rien liens à a donné slug, SvelteKit ne va pas know il exists — et vous’ll hit le classic construire erreur que routes “étaient marked as prerenderable, mais étaient pas prerendered.”

Le corriger est an explicit entries function (or config.kit.prerender.entries) que enumerates le parameter valeurs:

// src/routes/blog/[slug]/+page.server.js
export const prerender = true;

export function entries() {
  return [
    { slug: 'hello-world' },
    { slug: 'sveltekit-deployment-seo' },
  ];
}

En pratique vous generate que liste depuis votre CMS or contenu directory. Sans il, prerendering seulement covers le slugs le lien robot d’exploration se produit à trouver.

Le /blog/[slug] modèle dans le wild

Put le deux ensemble et vous ont le canonical mixed-site setup: prerender = 'auto' plus an entries function que renvoie votre recent et popular posts. Ceux obtenir static HTML à construire temps; n’importe quoi pas dans le liste falls via à SSR on demand. Nouveau posts rendre dynamically jusqu’à le suivant construire prerenders les. c’est le pragmatic middle ground entre “prerender all 40,000 posts every build” et “render every post on every request.”

Edge runtime constraints que affecter SEO

config.runtime = 'edge' is per-route (on Vercel)

Edge n’est pas an tous-or-rien switch. On Vercel c’est a per-route page option:

// +page.server.js or +server.js
export const config = { runtime: 'edge' };

Que signifie vous pouvez push élevé-traffic, cacheable routes à le edge pour faible TTFB pendant que keeping Node-dependent routes on le standard serverless (Node) runtime dans le même deployment. Mix deliberately.

Aucun fs, aucun arbitrary Node APIs

Le edge runtimes — Cloudflare Workers, Vercel Edge Functions, Netlify’s Deno Edge Functions — ne pas provide Node’s fs. Cloudflare’s docs: “Vous pouvez’t utiliser fs dans Cloudflare Workers.” Vercel’s: “Vous pouvez’t utiliser fs dans edge functions.” Les deux point à le même deux escape hatches: utiliser le read helper depuis $app/server à accès bundled assets, or “prerender the routes in question” donc le fichier accès se produit à construire temps au lieu de à requête temps.

«The SEO-adjacent cases where this bites: dynamic OG-image generation that reads a font or template file, file-based redirect maps, or a sitemap endpoint that reads content off disk. Any of those either moves to $app/server’s read() or moves to prerender/build time. It’s not a blocker — it’s a “know before you pick edge” constraint. » (Traduction) (Résumé en français de la section soixante-six, sous-partie un : le texte source est conservé pour vérification lors de la relecture francophone.)

Cold commence et TTFB — quand edge aide et quand il ne fait pas

Edge functions encore cold-commencer. A cold edge function on son premier requête peut être slower que a warm Node serveur, et dramatically slower que a prerendered fichier servi depuis cache. Edge wins quand le function stays warm or quand c’est paired avec aggressive mise en cache donc la plupart requêtes jamais hit le function à tout. Il est pas automatiquement le fastest option — “deploy to the edge” n’est pas a synonym pour “faster.” Pour a contenu site, prerendered static sortie beats edge SSR on TTFB chaque temps, parce que il y a aucun function à commencer.

Generating sitemap.xml et robots.txt (SvelteKit ne va pas)

Ce est le gap la plupart SvelteKit tutorials skip et la plupart audits catch. SvelteKit generates aucun sitemap.xml et aucun robots.txt automatiquement — regardless de adapter, regardless de comment nombreux pages vous prerender. A entièrement static site avec thousands de prerendered pages encore ships avec aucun sitemap unless vous construire un.

The +server.js endpoint pattern

Le idiomatic sitemap est a route endpoint que renvoie XML avec le correct Content-Type:

// src/routes/sitemap.xml/+server.js
export const prerender = true; // needed on adapter-static

export async function GET() {
  const urls = await getAllUrls(); // from your CMS/content
  const body = `<?xml version="1.0" encoding="UTF-8"?>
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
${urls.map((u) => `  <url><loc>${u}</loc></url>`).join('\n')}
</urlset>`;

  return new Response(body, {
    headers: { 'Content-Type': 'application/xml' },
  });
}

The strategy dépend on votre adapter

Here’s the partie que ties ce whole article ensemble: votre sitemap strategy is downstream of votre adapter choice.

  • On adapter-static, le sitemap endpoint nécessite export const prerender = vrai donc c’est inclus dans le static sortie — il y a aucun serveur à runtime à generate il on requête. c’est baked à construire temps, qui signifie c’est seulement as fresh as votre dernier construire.
  • On a Node/serverless/edge adapter, le même endpoint peut generate le sitemap dynamically per requête depuis votre CMS or database — toujours actuel, aucun rebuild nécessaire. (On an edge adapter, remember le fs constraint: pull URLs depuis an API or binding, pas a disk lire.)

Donc le “should my sitemap be static or dynamic?” question n’est pas a séparé décision — il falls out de le adapter vous déjà chose.

robots.txt: static fichier vs. endpoint

Deux options. Drop a plain robots.txt dans votre static/ folder (servi à /robots.txt automatiquement), qui est le simplest choice et fine pour la plupart sites. Or generate il depuis a src/routes/robots.txt/+server.js endpoint quand vous besoin il à differ par environment (blocking robots d’exploration on staging, allowing les dans production, pour instance). Soit façon, ne pas bloquer votre /_app/ bundle or CSS — que breaks rendu pour moteurs que faire rendre.

«If you’re coming at this from the broader framework or JavaScript-SEO angle, the “where and when does rendering happen” logic here is the same logic that governs JavaScript SEO generally, and the SvelteKit fundamentals piece in this section covers the rendering modes and metadata patterns this article builds on top of. » (Traduction) (Résumé en français de la section quatre-vingts, sous-partie un : le texte source est conservé pour vérification lors de la relecture francophone.)

Ajouter une note d’expert

Épingler une citation d’expert

Nouvelle personne ? Créez son profil non revendiqué à /admin/experts/ → Épingler une citation d’expert d’abord.