SvelteKit Deployment SEO: Adapters, Prerendering, dan Edge rendering

SvelteKit's adapter dan per-route prerender settings decide where dan when Anda halaman render — dan itu drives TTFB, LCP, dan anggaran crawling. sebuah deployment-focused deep dive: choosing adapter-static/node/vercel/cloudflare/netlify, prerender = benar/salah/'auto', edge-runtime constraints, dan membangun sitemap.xml dan robots.txt.

Pertama kali diterbitkan: 3 Jul 2026 · Terakhir diperbarui: 3 Agu 2026 · Advanced
Bahasa

SvelteKit's adapter dan per-route prerender setting decide where dan when sebuah halaman renders — static HTML di bangun time, SSR pada sebuah server, atau SSR di edge — dan itu decision drives TTFB, which feeds LCP dan crawl capacity. Pick adapter-static untuk pure konten situs, sebuah node/vercel/cloudflare adapter dengan per-route prerender untuk mixed konten-plus-app situs, dan sebuah edge adapter when global TTFB penting (accepting cold starts dan no Node fs). prerender = 'auto' adalah mixed-situs alat. Edge runtimes dapat't read filesystem. dan SvelteKit generates no sitemap.xml atau robots.txt — Anda bangun itu sebagai +server.js endpoints, dengan strategy depending pada Anda adapter.

TL;DR — adapter doesn’t perubahan what SvelteKit renders — ini perubahan where dan when: bangun-time static (adapter-static), permintaan-time pada sebuah server Anda run (adapter-node), atau permintaan-time pada serverless/edge functions (adapter-vercel/-netlify/-cloudflare). Per-route prerender = true membangun static HTML dan drops route dari dynamic manifest; prerender = 'auto' prerenders dan mempertahankan ini di manifest — alat untuk mixed /blog/[slug] situs. Edge runtimes run pada V8 isolates: no Node fs, dan cold starts hurt TTFB, which feeds LCP dan (per Google’s crawl-budget doc) crawl capacity. SvelteKit generates no sitemap.xml atau robots.txt — bangun them sebagai +server.js endpoints, dan note strategy depends pada adapter. ini adalah sebuah narrower, deployment-focused companion untuk SvelteKit SEO fundamentals artikel di ini bagian; I assume Anda sudah know SvelteKit adalah SSR-oleh-default dan won’t re-litigate itu here.

one idea itu membuat semua dari ini click

adapter melakukan not perubahan what renders. ini perubahan where dan when. itu’s whole thing. SvelteKit docs put ini precisely: adapters “take the built app as input and generate output for deployment.” (terjemahan) “take dibangun app sebagai input dan generate output untuk deployment.” Evidence for this claim SvelteKit adapters take the built application as input and generate deployment-specific output. Scope: Deployment output; adapter choice can still constrain supported runtime features. Confidence: high · Verified: SvelteKit: Adapters Anda components, Anda load functions, Anda <svelte:head> metadata — identical di seluruh setiap adapter. What differs adalah:

  • When HTML adalah produced: di bangun time (static/prerendered) atau di permintaan time (SSR pada sebuah server, serverless function, atau edge function).
  • Where ini adalah produced: pada sebuah single origin server, pada sebuah regional serverless function, atau pada sebuah edge network close untuk pengunjung.

Everything below adalah sebuah consequence dari itu two axes.

Why deployment choices adalah SEO choices

chain adalah pendek dan well-documented: TTFB → LCP → crawl capacity.

Time untuk pertama Byte adalah how panjang host takes untuk start sending respons. sebuah prerendered file disajikan dari sebuah CDN cache memiliki sebuah near-zero TTFB. sebuah server itu memiliki untuk render halaman memiliki sebuah higher one. sebuah cold-starting serverless atau edge function dapat memiliki sebuah much higher one pada pertama hit. TTFB adalah sebuah direct input untuk Largest Contentful Paint — Anda dapat’t paint what Anda haven’t diterima — dan LCP adalah sebuah Core Web Vitals signal.

crawl side adalah where Google adalah sebagian besar explicit. dari 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.” (terjemahan) “jika situs responds quickly untuk sebuah while, limit goes up, meaning more connections dapat menjadi digunakan untuk crawl. jika situs slows down atau responds dengan server errors, limit goes down dan Google melakukan crawl less.” dan 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.” (terjemahan) “membuat Anda halaman efficient untuk muat. jika Google dapat muat dan render Anda halaman faster, kami mungkin menjadi able untuk baca selengkapnya konten dari Anda situs.” sebuah cold-starting edge function itu’s slow untuk respond adalah subject untuk yang sama dynamic sebagai sebuah slow origin server.

One honesty note up front: Google publishes no SvelteKit-spesifik guidance. There’s no doc atau Search Off Record episode naming SvelteKit adapters, prerender = 'auto', atau edge cold starts. What I’m doing here adalah applying Google’s umum rendering dan crawl-budget guidance untuk SvelteKit’s spesifik mechanics — not quoting sebuah rep who commented pada SvelteKit, because none memiliki. Google framing itu “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” (terjemahan) “server-side atau pre-rendering adalah masih sebuah great idea because ini membuat Anda situs web faster untuk pengguna dan crawler, dan not semua bot dapat run JavaScript” adalah closest official anchor, dan ini adalah framework-agnostic.

Choosing sebuah adapter untuk SEO outcomes

adapter-auto — zero-config default, dan -nya ceiling

baru SvelteKit projects ship dengan adapter-auto. ini detects platform — Vercel, Netlify, Cloudflare halaman, Azure, AWS — dan installs matching adapter di bangun time. ini adalah sebuah fine starting poin, tetapi there’s sebuah hard ceiling worth knowing: adapter-auto melakukan not take apa pun options. moment Anda perlu { edge: true }, Cloudflare bindings, Vercel ISR, atau apa pun platform-spesifik configuration, Anda install underlying adapter (adapter-vercel, adapter-cloudflare, etc.) directly. Treat auto sebagai sebuah scaffold, not sebuah production decision.

adapter-static — full SSG, untuk konten-pertama situs

adapter-static prerenders Anda whole situs untuk static files di bangun time. No server runs; sebuah host menyajikan flat HTML. Evidence for this claim adapter-static prerenders a SvelteKit site as static files. Scope: Routes must be prerenderable; performance outcomes depend on hosting and page design. Confidence: high · Verified: SvelteKit: Static site generation untuk sebuah konten-pertama situs ini adalah strongest SEO profile Anda dapat memiliki — lowest TTFB, no cold starts, nothing untuk fall di atas. one requirement adalah trap covered di length di fundamentals artikel: SSR harus stay pada selama bangun, atau Anda get empty shells alih-alih rendered HTML. I won’t re-jelaskan itu here beyond flagging ini.

catch adalah rigidity. Anything itu genuinely perlu server logic per permintaan (benar search, per-pengguna konten, form handling without sebuah ketiga-party endpoint) dapat’t live pada sebuah purely static bangun — which adalah exactly what next adapters adalah untuk.

adapter-node — sebuah server Anda control

adapter-node produces sebuah standalone Node.js server. Anda run ini, Anda scale ini, Anda own TTFB. ini adalah paling flexible option dan one dengan fewest runtime surprises — full Node APIs, including fs. ini adalah sebuah baik fit when Anda memiliki infrastructure sudah, perlu Node libraries itu edge runtimes dapat’t run, atau ingin predictable (non-cold-starting) respons times dari sebuah warm server. tradeoff adalah operational: Anda’re running sebuah server, dan -nya speed dan uptime adalah now Anda crawl capacity.

adapter-vercel — serverless, edge, dan ISR

adapter-vercel deploys untuk Vercel’s serverless functions oleh default, dengan several SEO-relevant levers set per route via export const config:

  • runtime: 'edge' moves itu route untuk Vercel’s edge runtime (more below).
  • regions controls where serverless functions run — closer untuk Anda pengguna (atau Anda database) berarti lower latency.
  • isr enables Incremental Static Regeneration: isr: { expiration: 60 } menyajikan sebuah cached static asset dan regenerates ini setelah window, giving “the performance and cost advantages of prerendered content with the flexibility of dynamically rendered content.” (terjemahan) “ performa dan cost advantages dari prerendered konten dengan flexibility dari dynamically rendered konten.” ISR adalah sebuah genuine fourth path antara pure-static dan pure-SSR — tetapi note docs’ own caveat: “Using ISR on a route with export const prerender = true will have no effect, since the route is prerendered at build time.” (terjemahan) “menggunakan ISR pada sebuah route dengan undefined akan memiliki no effect, since route adalah prerendered di bangun time.” ISR dan prerender adalah alternatives, not stackable.

adapter-cloudflare — Workers/halaman, global edge

adapter-cloudflare targets Cloudflare Workers dan halaman — SSR pada sebuah global edge network, sering lowest TTFB untuk sebuah geographically spread audience. penting constraint adalah runtime: Workers run pada V8 isolates, not Node. dari docs: “You can’t use fs in Cloudflare Workers.” (terjemahan) “Anda dapat’t gunakan fs di Cloudflare Workers.” beberapa Node APIs berfungsi hanya behind nodejs_compat compatibility flag, dan bahkan lalu mendukung isn’t one-untuk-one. jika Anda adalah reading files di permintaan time (sebuah peta pengalihan, sebuah data file, custom OG-image inputs), itu code perlu sebuah rethink — covered di edge bagian below.

( older adapter-cloudflare-workers adalah deprecated; baru projects gunakan adapter-cloudflare, which handles both Workers dan halaman. jika Anda’re pada old one, migrating adalah recommended path.)

adapter-netlify — functions atau Edge Functions (Deno)

adapter-netlify deploys untuk Netlify’s Node-based functions oleh default, atau untuk Deno-based Edge Functions dengan edge: true. sama shape sebagai Vercel: default serverless dengan sebuah edge opt-di. One SvelteKit-spesifik footnote — Netlify Forms memerlukan form’s halaman untuk menjadi prerendered so Netlify dapat detect form markup di deploy time, which adalah sebuah kecil “prerender this route” (terjemahan) “prerender ini route” requirement layered pada top dari adapter choice.

decision, di one line setiap

  • Pure konten situsadapter-static, prerender everything.
  • konten situs dengan dynamic pocketsadapter-node/-vercel/-cloudflare, prerender = true pada konten, false/'auto' pada dynamic routes.
  • App/dashboard dengan personalization → SSR-pertama (node atau edge), prerender hanya static shell (marketing, login).
  • Global, TTFB-critical audience → sebuah edge adapter untuk dynamic routes, accepting Node-API constraints dan cold-start reality.

( Decision Tree tab walks ini sebagai sebuah branching flow.)

Prerendering strategy untuk mixed situs

What true / false / 'auto' actually melakukan

export const prerender adalah sebuah per-route (atau per-layout) halaman option, dan three nilai aren’t hanya pada/off:

  • true — bangun ini route untuk static HTML di bangun time. Critically, ini adalah “excluded from manifests used for dynamic SSR, making your server (or serverless/edge functions) smaller.” (terjemahan) “excluded dari manifests digunakan untuk dynamic SSR, membuat Anda server (atau serverless/edge functions) smaller.” Once prerendered, route dapat’t fall back untuk dynamic rendering — ini adalah static, full stop.
  • false — selalu render pada permintaan. No static file.
  • 'auto' — mixed-situs alat. ini prerenders route dan mempertahankan ini di dynamic server manifest, so yang sama route dapat menjadi disajikan statically untuk known paths dan server-rendered untuk rest. ini adalah dibangun untuk exactly case docs describe: sebuah route like /blog/[slug] “where you want to prerender your most recent/popular content but server-render the long tail.” (terjemahan) “where Anda ingin prerender Anda sebagian besar recent/popular konten tetapi server-render panjang tail.”

Because prerendered routes shrink server bundle, sebuah mostly-prerendered situs dengan sebuah few 'auto'/false routes deploys sebuah smaller, cheaper, faster function — sebuah efficiency win independent dari SEO.

Dynamic routes perlu sebuah entries function

prerender crawler discovers halaman oleh following <a> tautan dari Anda entry poin. itu berfungsi untuk static routes, tetapi sebuah dynamic route like /blog/[slug] memiliki no fixed URL untuk crawler untuk temukan. jika nothing tautan untuk sebuah given slug, SvelteKit won’t know ini exists — dan Anda’ll hit classic bangun error itu routes “were marked as prerenderable, but were not prerendered.” (terjemahan) “adalah marked sebagai prerenderable, tetapi adalah not prerendered.”

fix adalah sebuah explicit entries function (atau config.kit.prerender.entries) itu enumerates parameter nilai:

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

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

dalam praktik Anda generate itu list dari Anda CMS atau konten directory. Without ini, prerendering hanya covers slugs tautan crawler happens untuk temukan.

/blog/[slug] pattern di wild

Put two together dan Anda memiliki canonical mixed-situs setup: prerender = 'auto' plus sebuah entries function itu mengembalikan Anda recent dan popular posts. itu get static HTML di bangun time; anything not di list falls melalui untuk SSR pada demand. baru posts render dynamically until next bangun prerenders them. ini adalah pragmatic middle ground antara “prerender all 40,000 posts every build” (terjemahan) “prerender semua 40 000 posts setiap bangun” dan “render every post on every request.” (terjemahan) “render setiap post pada setiap permintaan.”

Edge runtime constraints itu affect SEO

config.runtime = 'edge' adalah per-route (pada Vercel)

Edge isn’t sebuah semua-atau-nothing switch. pada Vercel ini adalah sebuah per-route halaman option:

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

itu berarti Anda dapat push tinggi-traffic, cacheable routes untuk edge untuk rendah TTFB while keeping Node-dependent routes pada standard serverless (Node) runtime di yang sama deployment. Mix deliberately.

No fs, no arbitrary Node APIs

edge runtimes — Cloudflare Workers, Vercel Edge Functions, Netlify’s Deno Edge Functions — don’t menyediakan Node’s fs. Cloudflare’s docs: “You can’t use fs in Cloudflare Workers.” (terjemahan) “Anda dapat’t gunakan fs di Cloudflare Workers.” Vercel’s: “You can’t use fs in edge functions.” (terjemahan) “Anda dapat’t gunakan fs di edge functions.” Both poin untuk yang sama two escape hatches: gunakan read helper dari $app/server untuk access bundled assets, atau “prerender the routes in question” (terjemahan) “prerender routes di pertanyaan” so file access happens di bangun time alih-alih di permintaan time.

SEO-adjacent cases where ini bites: dynamic OG-image generation itu reads sebuah font atau template file, file-based redirect maps, atau sebuah sitemap endpoint itu reads konten off disk. apa pun dari itu either moves untuk $app/server’s read() atau moves untuk prerender/bangun time. ini adalah not sebuah blocker — ini adalah sebuah “know before you pick edge” (terjemahan) “know sebelum Anda pick edge” constraint.

Cold starts dan TTFB — when edge helps dan when ini doesn’t

Edge functions masih cold-start. sebuah cold edge function pada -nya pertama permintaan dapat menjadi slower daripada sebuah warm Node server, dan dramatically slower daripada sebuah prerendered file disajikan dari cache. Edge wins when function stays warm atau when ini adalah paired dengan aggressive caching so sebagian besar permintaan tidak pernah hit function di semua. ini adalah not automatically fastest option — “deploy to the edge” (terjemahan) “deploy untuk edge” adalah not sebuah synonym untuk “faster.” (terjemahan) “faster.” untuk sebuah konten situs, prerendered static output beats edge SSR pada TTFB setiap time, because there’s no function untuk start.

Generating sitemap.xml dan robots.txt (SvelteKit won’t)

ini adalah gap sebagian besar SvelteKit tutorials skip dan sebagian besar audits catch. SvelteKit generates no sitemap.xml dan no robots.txt automatically — regardless dari adapter, regardless dari how banyak halaman Anda prerender. sebuah fully static situs dengan thousands dari prerendered halaman masih ships dengan no sitemap unless Anda bangun one.

+server.js endpoint pattern

idiomatic sitemap adalah sebuah route endpoint itu mengembalikan XML dengan right 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' },
  });
}

strategy depends pada Anda adapter

Here’s bagian itu ties ini whole artikel together: Anda sitemap strategy adalah downstream dari Anda adapter choice.

  • pada adapter-static, sitemap endpoint perlu export const prerender = true so ini adalah disertakan di static output — there’s no server di runtime untuk generate ini pada permintaan. ini adalah baked di bangun time, which berarti ini adalah hanya sebagai fresh sebagai Anda last bangun.
  • pada sebuah Node/serverless/edge adapter, yang sama endpoint dapat generate sitemap dynamically per permintaan dari Anda CMS atau database — selalu saat ini, no rebuild needed. (pada sebuah edge adapter, remember fs constraint: pull URLs dari sebuah API atau binding, not sebuah disk read.)

So “should my sitemap be static or dynamic?” (terjemahan) “seharusnya my sitemap menjadi static atau dynamic?” pertanyaan isn’t sebuah separate decision — ini falls out dari adapter Anda sudah chose.

robots.txt: static file vs. endpoint

Two options. Drop sebuah plain robots.txt di Anda static/ folder (disajikan di /robots.txt automatically), which adalah simplest choice dan fine untuk sebagian besar situs. atau generate ini dari sebuah src/routes/robots.txt/+server.js endpoint when Anda perlu ini untuk differ oleh environment (blocking crawler pada staging, allowing them di production, misalnya). Either cara, don’t block Anda /_app/ bundle atau CSS — itu breaks rendering untuk mesin itu melakukan render.

jika Anda’re coming di ini dari broader framework atau JavaScript-SEO angle, “where and when does rendering happen” (terjemahan) “where dan when melakukan rendering happen” logic here adalah yang sama logic itu governs JavaScript SEO umumnya, dan SvelteKit fundamentals piece di ini bagian covers rendering modes dan metadata patterns ini artikel membangun pada top dari.

Add an expert note

Pin an expert quote

New person? Create their unclaimed profile at /admin/experts/ → Pin a quote first.