Loading...
{:then component} . ## Other Editors If you use a different editor, these community guides might be useful for you: - [WebStorm Svelte: Debug Your Application](https://www.jetbrains.com/help/webstorm/svelte.html#ws_svelte_debug) - [Debugging JavaScript Frameworks in Neovim](https://theosteiner.de/debugging-javascript-frameworks-in-neovim) ## Google Chrome and Microsoft Edge Developer Tools It's possible to debug Node.js applications using a browser-based debugger. > [!NOTE] Note this only works with debugging client-side SvelteKit source maps. 1. Run the `--inspect` flag when starting the Vite server with Node.js. For instance: `NODE_OPTIONS="--inspect" npm run dev` 2. Open your site in a new tab. Typically at `localhost:5173`. 3. Open your browser's dev tools, and click on the "Open dedicated DevTools for Node.js" icon near the top-left. It should display the Node.js logo. 4. Set up breakpoints and debug your application. You may alternatively open the debugger devtools by navigating to `chrome://inspect` in Google Chrome, or `edge://inspect` in Microsoft Edge. ## References - [Debugging Node.js](https://nodejs.org/en/learn/getting-started/debugging) --- title: Migrating to SvelteKit v2 --- Upgrading from SvelteKit version 1 to version 2 should be mostly seamless. There are a few breaking changes to note, which are listed here. You can use `npx sv migrate sveltekit-2` to migrate some of these changes automatically. We highly recommend upgrading to the most recent 1.x version before upgrading to 2.0, so that you can take advantage of targeted deprecation warnings. We also recommend [updating to Svelte 4](../svelte/v4-migration-guide) first: Later versions of SvelteKit 1.x support it, and SvelteKit 2.0 requires it. ## `redirect` and `error` are no longer thrown by you Previously, you had to `throw` the values returned from `error(...)` and `redirect(...)` yourself. In SvelteKit 2 this is no longer the case — calling the functions is sufficient. ```js import { error } from '@sveltejs/kit' // ... ---throw error(500, 'something went wrong');--- +++error(500, 'something went wrong');+++ ``` `svelte-migrate` will do these changes automatically for you. If the error or redirect is thrown inside a `try {...}` block (hint: don't do this!), you can distinguish them from unexpected errors using [`isHttpError`](@sveltejs-kit#isHttpError) and [`isRedirect`](@sveltejs-kit#isRedirect) imported from `@sveltejs/kit`. ## path is required when setting cookies When receiving a `Set-Cookie` header that doesn't specify a `path`, browsers will [set the cookie path](https://www.rfc-editor.org/rfc/rfc6265#section-5.1.4) to the parent of the resource in question. This behaviour isn't particularly helpful or intuitive, and frequently results in bugs because the developer expected the cookie to apply to the domain as a whole. As of SvelteKit 2.0, you need to set a `path` when calling `cookies.set(...)`, `cookies.delete(...)` or `cookies.serialize(...)` so that there's no ambiguity. Most of the time, you probably want to use `path: '/'`, but you can set it to whatever you like, including relative paths — `''` means 'the current path', `'.'` means 'the current directory'. ```js /** @type {import('./$types').PageServerLoad} */ export function load({ cookies }) { cookies.set(name, value, +++{ path: '/' }+++); return { response } } ``` `svelte-migrate` will add comments highlighting the locations that need to be adjusted. ## Top-level promises are no longer awaited In SvelteKit version 1, if the top-level properties of the object returned from a `load` function were promises, they were automatically awaited. With the introduction of [streaming](/blog/streaming-snapshots-sveltekit) this behavior became a bit awkward as it forces you to nest your streamed data one level deep. As of version 2, SvelteKit no longer differentiates between top-level and non-top-level promises. To get back the blocking behavior, use `await` (with `Promise.all` to prevent waterfalls, where appropriate): ```js // @filename: ambient.d.ts declare const url: string; // @filename: index.js // ---cut--- // If you have a single promise /** @type {import('./$types').PageServerLoad} */ export +++async+++ function load({ fetch }) { const response = +++await+++ fetch(url).then(r => r.json()); return { response } } ``` ```js // @filename: ambient.d.ts declare const url1: string; declare const url2: string; // @filename: index.js // ---cut--- // If you have multiple promises /** @type {import('./$types').PageServerLoad} */ export +++async+++ function load({ fetch }) { --- const a = fetch(url1).then(r => r.json());--- --- const b = fetch(url2).then(r => r.json());--- +++ const [a, b] = await Promise.all([ fetch(url1).then(r => r.json()), fetch(url2).then(r => r.json()), ]);+++ return { a, b }; } ``` ## goto(...) changes `goto(...)` no longer accepts external URLs. To navigate to an external URL, use `window.location.href = url`. The `state` object now determines `$page.state` and must adhere to the `App.PageState` interface, if declared. See [shallow routing](shallow-routing) for more details. ## paths are now relative by default In SvelteKit 1, `%sveltekit.assets%` in your `app.html` was replaced with a relative path by default (i.e. `.` or `..` or `../..` etc, depending on the path being rendered) during server-side rendering unless the [`paths.relative`](configuration#paths) config option was explicitly set to `false`. The same was true for `base` and `assets` imported from `$app/paths`, but only if the `paths.relative` option was explicitly set to `true`. This inconsistency is fixed in version 2. Paths are either always relative or always absolute, depending on the value of [`paths.relative`](configuration#paths). It defaults to `true` as this results in more portable apps: if the `base` is something other than the app expected (as is the case when viewed on the [Internet Archive](https://archive.org/), for example) or unknown at build time (as is the case when deploying to [IPFS](https://ipfs.tech/) and so on), fewer things are likely to break. ## Server fetches are not trackable anymore Previously it was possible to track URLs from `fetch`es on the server in order to rerun load functions. This poses a possible security risk (private URLs leaking), and as such it was behind the `dangerZone.trackServerFetches` setting, which is now removed. ## `preloadCode` arguments must be prefixed with `base` SvelteKit exposes two functions, [`preloadCode`]($app-navigation#preloadCode) and [`preloadData`]($app-navigation#preloadData), for programmatically loading the code and data associated with a particular path. In version 1, there was a subtle inconsistency — the path passed to `preloadCode` did not need to be prefixed with the `base` path (if set), while the path passed to `preloadData` did. This is fixed in SvelteKit 2 — in both cases, the path should be prefixed with `base` if it is set. Additionally, `preloadCode` now takes a single argument rather than _n_ arguments. ## `resolvePath` has been removed SvelteKit 1 included a function called `resolvePath` which allows you to resolve a route ID (like `/blog/[slug]`) and a set of parameters (like `{ slug: 'hello' }`) to a pathname. Unfortunately the return value didn't include the `base` path, limiting its usefulness in cases where `base` was set. As such, SvelteKit 2 replaces `resolvePath` with a (slightly better named) function called `resolveRoute`, which is imported from `$app/paths` and which takes `base` into account. ```js ---import { resolvePath } from '@sveltejs/kit'; import { base } from '$app/paths';--- +++import { resolveRoute } from '$app/paths';+++ ---const path = base + resolvePath('/blog/[slug]', { slug });--- +++const path = resolveRoute('/blog/[slug]', { slug });+++ ``` `svelte-migrate` will do the method replacement for you, though if you later prepend the result with `base`, you need to remove that yourself. ## Improved error handling Errors are handled inconsistently in SvelteKit 1. Some errors trigger the `handleError` hook but there is no good way to discern their status (for example, the only way to tell a 404 from a 500 is by seeing if `event.route.id` is `null`), while others (such as 405 errors for `POST` requests to pages without actions) don't trigger `handleError` at all, but should. In the latter case, the resulting `$page.error` will deviate from the [`App.Error`](types#Error) type, if it is specified. SvelteKit 2 cleans this up by calling `handleError` hooks with two new properties: `status` and `message`. For errors thrown from your code (or library code called by your code) the status will be `500` and the message will be `Internal Error`. While `error.message` may contain sensitive information that should not be exposed to users, `message` is safe. ## Dynamic environment variables cannot be used during prerendering The `$env/dynamic/public` and `$env/dynamic/private` modules provide access to _run time_ environment variables, as opposed to the _build time_ environment variables exposed by `$env/static/public` and `$env/static/private`. During prerendering in SvelteKit 1, they are one and the same. As such, prerendered pages that make use of 'dynamic' environment variables are really 'baking in' build time values, which is incorrect. Worse, `$env/dynamic/public` is populated in the browser with these stale values if the user happens to land on a prerendered page before navigating to dynamically-rendered pages. Because of this, dynamic environment variables can no longer be read during prerendering in SvelteKit 2 — you should use the `static` modules instead. If the user lands on a prerendered page, SvelteKit will request up-to-date values for `$env/dynamic/public` from the server (by default from a module called `/_app/env.js`) instead of reading them from the server-rendered HTML. ## `form` and `data` have been removed from `use:enhance` callbacks If you provide a callback to [`use:enhance`](form-actions#Progressive-enhancement-use:enhance), it will be called with an object containing various useful properties. In SvelteKit 1, those properties included `form` and `data`. These were deprecated some time ago in favour of `formElement` and `formData`, and have been removed altogether in SvelteKit 2. ## Forms containing file inputs must use `multipart/form-data` If a form contains an ` ` but does not have an `enctype="multipart/form-data"` attribute, non-JS submissions will omit the file. SvelteKit 2 will throw an error if it encounters a form like this during a `use:enhance` submission to ensure that your forms work correctly when JavaScript is not present. ## Generated `tsconfig.json` is more strict Previously, the generated `tsconfig.json` was trying its best to still produce a somewhat valid config when your `tsconfig.json` included `paths` or `baseUrl`. In SvelteKit 2, the validation is more strict and will warn when you use either `paths` or `baseUrl` in your `tsconfig.json`. These settings are used to generate path aliases and you should use [the `alias` config](configuration#alias) option in your `svelte.config.js` instead, to also create a corresponding alias for the bundler. ## `getRequest` no longer throws errors The `@sveltejs/kit/node` module exports helper functions for use in Node environments, including `getRequest` which turns a Node [`ClientRequest`](https://nodejs.org/api/http.html#class-httpclientrequest) into a standard [`Request`](https://developer.mozilla.org/en-US/docs/Web/API/Request) object. In SvelteKit 1, `getRequest` could throw if the `Content-Length` header exceeded the specified size limit. In SvelteKit 2, the error will not be thrown until later, when the request body (if any) is being read. This enables better diagnostics and simpler code. ## `vitePreprocess` is no longer exported from `@sveltejs/kit/vite` Since `@sveltejs/vite-plugin-svelte` is now a peer dependency, SvelteKit 2 no longer re-exports `vitePreprocess`. You should import it directly from `@sveltejs/vite-plugin-svelte`. ## Updated dependency requirements SvelteKit 2 requires Node `18.13` or higher, and the following minimum dependency versions: - `svelte@4` - `vite@5` - `typescript@5` - `@sveltejs/vite-plugin-svelte@3` (this is now required as a `peerDependency` of SvelteKit — previously it was directly depended upon) - `@sveltejs/adapter-cloudflare@3` (if you're using these adapters) - `@sveltejs/adapter-cloudflare-workers@2` - `@sveltejs/adapter-netlify@3` - `@sveltejs/adapter-node@2` - `@sveltejs/adapter-static@3` - `@sveltejs/adapter-vercel@4` `svelte-migrate` will update your `package.json` for you. As part of the TypeScript upgrade, the generated `tsconfig.json` (the one your `tsconfig.json` extends from) now uses `"moduleResolution": "bundler"` (which is recommended by the TypeScript team, as it properly resolves types from packages with an `exports` map in package.json) and `verbatimModuleSyntax` (which replaces the existing `importsNotUsedAsValues ` and `preserveValueImports` flags — if you have those in your `tsconfig.json`, remove them. `svelte-migrate` will do this for you). ## SvelteKit 2.12: $app/stores deprecated SvelteKit 2.12 introduced `$app/state` based on the [Svelte 5 runes API](/docs/svelte/what-are-runes). `$app/state` provides everything that `$app/stores` provides but with more flexibility as to where and how you use it. Most importantly, the `page` object is now fine-grained, e.g. updates to `page.state` will not invalidate `page.data` and vice-versa. As a consequence, `$app/stores` is deprecated and subject to be removed in SvelteKit 3. We recommend [upgrading to Svelte 5](/docs/svelte/v5-migration-guide), if you haven't already, and then migrate away from `$app/stores`. Most of the replacements should be pretty simple: Replace the `$app/stores` import with `$app/state` and remove the `$` prefixes from the usage sites. ```svelte ---{$page.data}--- +++{page.data}+++ ``` Use `npx sv migrate app-state` to auto-migrate most of your `$app/stores` usages inside `.svelte` components. --- title: Migrating from Sapper rank: 1 --- SvelteKit is the successor to Sapper and shares many elements of its design. If you have an existing Sapper app that you plan to migrate to SvelteKit, there are a number of changes you will need to make. You may find it helpful to view [some examples](additional-resources#Examples) while migrating. ## package.json ### type: "module" Add `"type": "module"` to your `package.json`. You can do this step separately from the rest as part of an incremental migration if you are using Sapper 0.29.3 or newer. ### dependencies Remove `polka` or `express`, if you're using one of those, and any middleware such as `sirv` or `compression`. ### devDependencies Remove `sapper` from your `devDependencies` and replace it with `@sveltejs/kit` and whichever [adapter](adapters) you plan to use (see [next section](migrating#Project-files-Configuration)). ### scripts Any scripts that reference `sapper` should be updated: - `sapper build` should become `vite build` using the Node [adapter](adapters) - `sapper export` should become `vite build` using the static [adapter](adapters) - `sapper dev` should become `vite dev` - `node __sapper__/build` should become `node build` ## Project files The bulk of your app, in `src/routes`, can be left where it is, but several project files will need to be moved or updated. ### Configuration Your `webpack.config.js` or `rollup.config.js` should be replaced with a `svelte.config.js`, as documented [here](configuration). Svelte preprocessor options should be moved to `config.preprocess`. You will need to add an [adapter](adapters). `sapper build` is roughly equivalent to [adapter-node](adapter-node) while `sapper export` is roughly equivalent to [adapter-static](adapter-static), though you might prefer to use an adapter designed for the platform you're deploying to. If you were using plugins for filetypes that are not automatically handled by [Vite](https://vitejs.dev), you will need to find Vite equivalents and add them to the [Vite config](project-structure#Project-files-vite.config.js). ### src/client.js This file has no equivalent in SvelteKit. Any custom logic (beyond `sapper.start(...)`) should be expressed in your `+layout.svelte` file, inside an `onMount` callback. ### src/server.js When using `adapter-node` the equivalent is a [custom server](adapter-node#Custom-server). Otherwise, this file has no direct equivalent, since SvelteKit apps can run in serverless environments. ### src/service-worker.js Most imports from `@sapper/service-worker` have equivalents in [`$service-worker`]($service-worker): - `files` is unchanged - `routes` has been removed - `shell` is now `build` - `timestamp` is now `version` ### src/template.html The `src/template.html` file should be renamed `src/app.html`. Remove `%sapper.base%`, `%sapper.scripts%` and `%sapper.styles%`. Replace `%sapper.head%` with `%sveltekit.head%` and `%sapper.html%` with `%sveltekit.body%`. The `` is no longer necessary. ### src/node_modules A common pattern in Sapper apps is to put your internal library in a directory inside `src/node_modules`. This doesn't work with Vite, so we use [`src/lib`]($lib) instead. ## Pages and layouts ### Renamed files Routes now are made up of the folder name exclusively to remove ambiguity, the folder names leading up to a `+page.svelte` correspond to the route. See [the routing docs](routing) for an overview. The following shows a old/new comparison: | Old | New | | ------------------------- | ------------------------- | | routes/about/index.svelte | routes/about/+page.svelte | | routes/about.svelte | routes/about/+page.svelte | Your custom error page component should be renamed from `_error.svelte` to `+error.svelte`. Any `_layout.svelte` files should likewise be renamed `+layout.svelte`. [Any other files are ignored](routing#Other-files). ### Imports The `goto`, `prefetch` and `prefetchRoutes` imports from `@sapper/app` should be replaced with `goto`, `preloadData` and `preloadCode` imports respectively from [`$app/navigation`]($app-navigation). The `stores` import from `@sapper/app` should be replaced — see the [Stores](migrating#Pages-and-layouts-Stores) section below. Any files you previously imported from directories in `src/node_modules` will need to be replaced with [`$lib`]($lib) imports. ### Preload As before, pages and layouts can export a function that allows data to be loaded before rendering takes place. This function has been renamed from `preload` to [`load`](load), it now lives in a `+page.js` (or `+layout.js`) next to its `+page.svelte` (or `+layout.svelte`), and its API has changed. Instead of two arguments — `page` and `session` — there is a single `event` argument. There is no more `this` object, and consequently no `this.fetch`, `this.error` or `this.redirect`. Instead, you can get [`fetch`](load#Making-fetch-requests) from the input methods, and both [`error`](load#Errors) and [`redirect`](load#Redirects) are now thrown. ### Stores In Sapper, you would get references to provided stores like so: ```js // @filename: ambient.d.ts declare module '@sapper/app'; // @filename: index.js // ---cut--- import { stores } from '@sapper/app'; const { preloading, page, session } = stores(); ``` The `page` store still exists; `preloading` has been replaced with a `navigating` store that contains `from` and `to` properties. `page` now has `url` and `params` properties, but no `path` or `query`. You access them differently in SvelteKit. `stores` is now `getStores`, but in most cases it is unnecessary since you can import `navigating`, and `page` directly from [`$app/stores`]($app-stores). If you're on Svelte 5 and SvelteKit 2.12 or higher, consider using [`$app/state`]($app-state) instead. ### Routing Regex routes are no longer supported. Instead, use [advanced route matching](advanced-routing#Matching). ### Segments Previously, layout components received a `segment` prop indicating the child segment. This has been removed; you should use the more flexible `$page.url.pathname` (or `page.url.pathname`) value to derive the segment you're interested in. ### URLs In Sapper, all relative URLs were resolved against the base URL — usually `/`, unless the `basepath` option was used — rather than against the current page. This caused problems and is no longer the case in SvelteKit. Instead, relative URLs are resolved against the current page (or the destination page, for `fetch` URLs in `load` functions) instead. In most cases, it's easier to use root-relative (i.e. starts with `/`) URLs, since their meaning is not context-dependent. ### <a> attributes - `sapper:prefetch` is now `data-sveltekit-preload-data` - `sapper:noscroll` is now `data-sveltekit-noscroll` ## Endpoints In Sapper, [server routes](routing#server) received the `req` and `res` objects exposed by Node's `http` module (or the augmented versions provided by frameworks like Polka and Express). SvelteKit is designed to be agnostic as to where the app is running — it could be running on a Node server, but could equally be running on a serverless platform or in a Cloudflare Worker. For that reason, you no longer interact directly with `req` and `res`. Your endpoints will need to be updated to match the new signature. To support this environment-agnostic behavior, `fetch` is now available in the global context, so you don't need to import `node-fetch`, `cross-fetch`, or similar server-side fetch implementations in order to use it. ## Integrations See [integrations](./integrations) for detailed information about integrations. ### HTML minifier Sapper includes `html-minifier` by default. SvelteKit does not include this, but you can add it as a prod dependency and then use it through a [hook](hooks#Server-hooks-handle): ```js // @filename: ambient.d.ts /// declare module 'html-minifier'; // @filename: index.js // ---cut--- import { minify } from 'html-minifier'; import { building } from '$app/environment'; const minification_options = { collapseBooleanAttributes: true, collapseWhitespace: true, conservativeCollapse: true, decodeEntities: true, html5: true, ignoreCustomComments: [/^#/], minifyCSS: true, minifyJS: false, removeAttributeQuotes: true, removeComments: false, // some hydration code needs comments, so leave them in removeOptionalTags: true, removeRedundantAttributes: true, removeScriptTypeAttributes: true, removeStyleLinkTypeAttributes: true, sortAttributes: true, sortClassName: true }; /** @type {import('@sveltejs/kit').Handle} */ export async function handle({ event, resolve }) { let page = ''; return resolve(event, { transformPageChunk: ({ html, done }) => { page += html; if (done) { return building ? minify(page, minification_options) : page; } } }); } ``` Note that `prerendering` is `false` when using `vite preview` to test the production build of the site, so to verify the results of minifying, you'll need to inspect the built HTML files directly. --- title: Additional resources --- ## FAQs Please see the [SvelteKit FAQ](faq) for solutions to common issues and helpful tips and tricks. The [Svelte FAQ](../svelte/faq) and [`vite-plugin-svelte` FAQ](https://github.com/sveltejs/vite-plugin-svelte/blob/main/docs/faq.md) may also be helpful for questions deriving from those libraries. ## Examples We've written and published a few different SvelteKit sites as examples: - [`sveltejs/realworld`](https://github.com/sveltejs/realworld) contains an example blog site - [A HackerNews clone](https://github.com/sveltejs/sites/tree/master/sites/hn.svelte.dev) - [`svelte.dev`](https://github.com/sveltejs/svelte.dev) SvelteKit users have also published plenty of examples on GitHub, under the [#sveltekit](https://github.com/topics/sveltekit) and [#sveltekit-template](https://github.com/topics/sveltekit-template) topics, as well as on [the Svelte Society site](https://sveltesociety.dev/templates?category=sveltekit). Note that these have not been vetted by the maintainers and may not be up to date. ## Support You can ask for help on [Discord](/chat) and [StackOverflow](https://stackoverflow.com/questions/tagged/sveltekit). Please first search for information related to your issue in the FAQ, Google or another search engine, issue tracker, and Discord chat history in order to be respectful of others' time. There are many more people asking questions than answering them, so this will help in allowing the community to grow in a scalable fashion. --- title: Glossary --- The core of SvelteKit provides a highly configurable rendering engine. This section describes some of the terms used when discussing rendering. A reference for setting these options is provided in the documentation above. ## CSR Client-side rendering (CSR) is the generation of the page contents in the web browser using JavaScript. In SvelteKit, client-side rendering will be used by default, but you can turn off JavaScript with [the `csr = false` page option](page-options#csr). ## Edge Rendering on the edge refers to rendering an application in a content delivery network (CDN) near the user. Edge rendering allows the request and response for a page to travel a shorter distance thus improving latency. ## Hydration Svelte components store some state and update the DOM when the state is updated. When fetching data during SSR, by default SvelteKit will store this data and transmit it to the client along with the server-rendered HTML. The components can then be initialized on the client with that data without having to call the same API endpoints again. Svelte will then check that the DOM is in the expected state and attach event listeners in a process called hydration. Once the components are fully hydrated, they can react to changes to their properties just like any newly created Svelte component. In SvelteKit, pages will be hydrated by default, but you can turn off JavaScript with [the `csr = false` page option](page-options#csr). ## ISR Incremental static regeneration (ISR) allows you to generate static pages on your site as visitors request those pages without redeploying. This may reduces build times compared to [SSG](#SSG) sites with a large number of pages. You can do [ISR with `adapter-vercel`](adapter-vercel#Incremental-Static-Regeneration). ## MPA Traditional applications that render each page view on the server — such as those written in languages other than JavaScript — are often referred to as multi-page apps (MPA). ## Prerendering Prerendering means computing the contents of a page at build time and saving the HTML for display. This approach has the same benefits as traditional server-rendered pages, but avoids recomputing the page for each visitor and so scales nearly for free as the number of visitors increases. The tradeoff is that the build process is more expensive and prerendered content can only be updated by building and deploying a new version of the application. Not all pages can be prerendered. The basic rule is this: for content to be prerenderable, any two users hitting it directly must get the same content from the server, and the page must not contain [actions](form-actions). Note that you can still prerender content that is loaded based on the page's parameters as long as all users will be seeing the same prerendered content. Pre-rendered pages are not limited to static content. You can build personalized pages if user-specific data is fetched and rendered client-side. This is subject to the caveat that you will experience the downsides of not doing SSR for that content as discussed above. In SvelteKit, you can control prerendering with [the `prerender` page option](page-options#prerender) and [`prerender` config](configuration#prerender) in `svelte.config.js`. ## PWA A progressive web app (PWA) is an app that's built using web APIs and technologies, but functions like a mobile or desktop app. Sites served as [PWAs can be installed](https://web.dev/learn/pwa/installation), allowing you to add a shortcut to the application on your launcher, home screen, or start menu. Many PWAs will utilize [service workers](service-workers) to build offline capabilities. ## Routing By default, when you navigate to a new page (by clicking on a link or using the browser's forward or back buttons), SvelteKit will intercept the attempted navigation and handle it instead of allowing the browser to send a request to the server for the destination page. SvelteKit will then update the displayed contents on the client by rendering the component for the new page, which in turn can make calls to the necessary API endpoints. This process of updating the page on the client in response to attempted navigation is called client-side routing. In SvelteKit, client-side routing will be used by default, but you can skip it with [`data-sveltekit-reload`](link-options#data-sveltekit-reload). ## SPA A single-page app (SPA) is an application in which all requests to the server load a single HTML file which then does client-side rendering of the requested contents based on the requested URL. All navigation is handled on the client-side in a process called client-side routing with per-page contents being updated and common layout elements remaining largely unchanged. SPAs do not provide SSR and thus have worse performance and SEO characteristics. However, some applications are not greatly impacted by these shortcomings such as a complex business application behind a login where SEO would not be important and it is known that users will be accessing the application from a consistent computing environment. In SvelteKit, you can [build an SPA with `adapter-static`](single-page-apps). ## SSG Static Site Generation (SSG) is a term that refers to a site where every page is prerendered. One benefit of fully prerendering a site is that you do not need to maintain or pay for servers to perform SSR. Once generated, the site can be served from CDNs, leading to great “time to first byte” performance. This delivery model is often referred to as JAMstack. In SvelteKit, you can do static site generation by using [`adapter-static`](adapter-static) or by configuring every page to be prerendered using [the `prerender` page option](page-options#prerender) or [`prerender` config](configuration#prerender) in `svelte.config.js`. ## SSR Server-side rendering (SSR) is the generation of the page contents on the server. SSR is generally preferred for SEO. While some search engines can index content that is dynamically generated on the client-side it may take longer even in these cases. It also tends to improve perceived performance and makes your app accessible to users if JavaScript fails or is disabled (which happens [more often than you probably think](https://kryogenix.org/code/browser/everyonehasjs.html)). In SvelteKit, pages are server-side rendered by default. You can disable SSR with [the `ssr` page option](page-options#ssr). --- title: Appendix --- --- title: @sveltejs/kit --- > MODULE: @sveltejs/kit ## Private types The following are referenced by the public types documented above, but cannot be imported directly: > TYPES: Private types --- title: @sveltejs/kit/hooks --- > MODULE: @sveltejs/kit/hooks --- title: @sveltejs/kit/node/polyfills --- > MODULE: @sveltejs/kit/node/polyfills --- title: @sveltejs/kit/node --- > MODULE: @sveltejs/kit/node --- title: @sveltejs/kit/vite --- > MODULE: @sveltejs/kit/vite --- title: $app/environment --- > MODULE: $app/environment --- title: $app/forms --- > MODULE: $app/forms --- title: $app/navigation --- > MODULE: $app/navigation --- title: $app/paths --- > MODULE: $app/paths --- title: $app/server --- > MODULE: $app/server --- title: $app/state --- SvelteKit makes three read-only state objects available via the `$app/state` module — `page`, `navigating` and `updated`. > [!NOTE] > This module was added in 2.12. If you're using an earlier version of SvelteKit, use [`$app/stores`]($app-stores) instead. > MODULE: $app/state --- title: $app/stores --- This module contains store-based equivalents of the exports from [`$app/state`]($app-state). If you're using SvelteKit 2.12 or later, use that module instead. > MODULE: $app/stores --- title: $env/dynamic/private --- > MODULE: $env/dynamic/private --- title: $env/dynamic/public --- > MODULE: $env/dynamic/public --- title: $env/static/private --- > MODULE: $env/static/private --- title: $env/static/public --- > MODULE: $env/static/public --- title: $lib --- SvelteKit automatically makes files under `src/lib` available using the `$lib` import alias. You can change which directory this alias points to in your [config file](configuration#files). ```svelte A reusable component ``` ```svelte ``` --- title: $service-worker --- > MODULE: $service-worker --- title: Configuration --- Your project's configuration lives in a `svelte.config.js` file at the root of your project. As well as SvelteKit, this config object is used by other tooling that integrates with Svelte such as editor extensions. ```js /// file: svelte.config.js // @filename: ambient.d.ts declare module '@sveltejs/adapter-auto' { const plugin: () => import('@sveltejs/kit').Adapter; export default plugin; } // @filename: index.js // ---cut--- import adapter from '@sveltejs/adapter-auto'; /** @type {import('@sveltejs/kit').Config} */ const config = { kit: { adapter: adapter() } }; export default config; ``` ## Config > TYPES: Configuration#Config ## KitConfig The `kit` property configures SvelteKit, and can have the following properties: > EXPANDED_TYPES: Configuration#KitConfig --- title: Command Line Interface --- SvelteKit projects use [Vite](https://vitejs.dev), meaning you'll mostly use its CLI (albeit via `npm run dev/build/preview` scripts): - `vite dev` — start a development server - `vite build` — build a production version of your app - `vite preview` — run the production version locally However SvelteKit includes its own CLI for initialising your project: ## svelte-kit sync `svelte-kit sync` creates the `tsconfig.json` and all generated types (which you can import as `./$types` inside routing files) for your project. When you create a new project, it is listed as the `prepare` script and will be run automatically as part of the npm lifecycle, so you should not ordinarily have to run this command. --- title: Types --- ## Generated types The `RequestHandler` and `Load` types both accept a `Params` argument allowing you to type the `params` object. For example this endpoint expects `foo`, `bar` and `baz` params: ```js /// file: src/routes/[foo]/[bar]/[baz]/+server.js // @errors: 2355 2322 1360 /** @type {import('@sveltejs/kit').RequestHandler<{ foo: string; bar: string; baz: string }>} */ export async function GET({ params }) { // ... } ``` Needless to say, this is cumbersome to write out, and less portable (if you were to rename the `[foo]` directory to `[qux]`, the type would no longer reflect reality). To solve this problem, SvelteKit generates `.d.ts` files for each of your endpoints and pages: ```ts /// file: .svelte-kit/types/src/routes/[foo]/[bar]/[baz]/$types.d.ts /// link: true import type * as Kit from '@sveltejs/kit'; type RouteParams = { foo: string; bar: string; baz: string; }; export type RequestHandler = Kit.RequestHandler; export type PageLoad = Kit.Load; ``` These files can be imported into your endpoints and pages as siblings, thanks to the [`rootDirs`](https://www.typescriptlang.org/tsconfig#rootDirs) option in your TypeScript configuration: ```js /// file: src/routes/[foo]/[bar]/[baz]/+server.js // @filename: $types.d.ts import type * as Kit from '@sveltejs/kit'; type RouteParams = { foo: string; bar: string; baz: string; } export type RequestHandler = Kit.RequestHandler; // @filename: index.js // @errors: 2355 2322 // ---cut--- /** @type {import('./$types').RequestHandler} */ export async function GET({ params }) { // ... } ``` ```js /// file: src/routes/[foo]/[bar]/[baz]/+page.js // @filename: $types.d.ts import type * as Kit from '@sveltejs/kit'; type RouteParams = { foo: string; bar: string; baz: string; } export type PageLoad = Kit.Load; // @filename: index.js // @errors: 2355 // ---cut--- /** @type {import('./$types').PageLoad} */ export async function load({ params, fetch }) { // ... } ``` The return types of the load functions are then available through the `$types` module as `PageData` and `LayoutData` respectively, while the union of the return values of all `Actions` is available as `ActionData`. Starting with version 2.16.0, two additional helper types are provided: `PageProps` defines `data: PageData`, as well as `form: ActionData`, when there are actions defined, while `LayoutProps` defines `data: LayoutData`, as well as `children: Snippet`. ```svelte ``` > [!LEGACY] > Before 2.16.0: > ```svelte > > > ``` > > Using Svelte 4: > ```svelte > > > ``` > [!NOTE] For this to work, your own `tsconfig.json` or `jsconfig.json` should extend from the generated `.svelte-kit/tsconfig.json` (where `.svelte-kit` is your [`outDir`](configuration#outDir)): > > `{ "extends": "./.svelte-kit/tsconfig.json" }` ### Default tsconfig.json The generated `.svelte-kit/tsconfig.json` file contains a mixture of options. Some are generated programmatically based on your project configuration, and should generally not be overridden without good reason: ```json /// file: .svelte-kit/tsconfig.json { "compilerOptions": { "paths": { "$lib": ["../src/lib"], "$lib/*": ["../src/lib/*"] }, "rootDirs": ["..", "./types"] }, "include": [ "ambient.d.ts", "non-ambient.d.ts", "./types/**/$types.d.ts", "../vite.config.js", "../vite.config.ts", "../src/**/*.js", "../src/**/*.ts", "../src/**/*.svelte", "../tests/**/*.js", "../tests/**/*.ts", "../tests/**/*.svelte" ], "exclude": [ "../node_modules/**", "../src/service-worker.js", "../src/service-worker/**/*.js", "../src/service-worker.ts", "../src/service-worker/**/*.ts", "../src/service-worker.d.ts", "../src/service-worker/**/*.d.ts" ] } ``` Others are required for SvelteKit to work properly, and should also be left untouched unless you know what you're doing: ```json /// file: .svelte-kit/tsconfig.json { "compilerOptions": { // this ensures that types are explicitly // imported with `import type`, which is // necessary as Svelte/Vite cannot // otherwise compile components correctly "verbatimModuleSyntax": true, // Vite compiles one TypeScript module // at a time, rather than compiling // the entire module graph "isolatedModules": true, // Tell TS it's used only for type-checking "noEmit": true, // This ensures both `vite build` // and `svelte-package` work correctly "lib": ["esnext", "DOM", "DOM.Iterable"], "moduleResolution": "bundler", "module": "esnext", "target": "esnext" } } ``` ## $lib This is a simple alias to `src/lib`, or whatever directory is specified as [`config.kit.files.lib`](configuration#files). It allows you to access common components and utility modules without `../../../../` nonsense. ### $lib/server A subdirectory of `$lib`. SvelteKit will prevent you from importing any modules in `$lib/server` into client-side code. See [server-only modules](server-only-modules). ## app.d.ts The `app.d.ts` file is home to the ambient types of your apps, i.e. types that are available without explicitly importing them. Always part of this file is the `App` namespace. This namespace contains several types that influence the shape of certain SvelteKit features you interact with. > TYPES: App --- title: Reference --- --- title: SvelteKit ---