Skip to main content

Build and deploy

Vercel

Edit this page on GitHub

To deploy to Vercel, use adapter-vercel.

This adapter will be installed by default when you use adapter-auto, but adding it to your project allows you to specify Vercel-specific options.

Usage

Install with npm i -D @sveltejs/adapter-vercel, then add the adapter to your svelte.config.js:

svelte.config.js
ts
import adapter from '@sveltejs/adapter-vercel';
export default {
kit: {
adapter: adapter({
// see below for options that can be set here
})
}
};

Deployment configuration

To control how your routes are deployed to Vercel as functions, you can specify deployment configuration, either through the option shown above or with export const config inside +server.js, +page(.server).js and +layout(.server).js files.

For example you could deploy some parts of your app as Edge Functions...

about/+page.js
ts
/** @type {import('@sveltejs/adapter-vercel').Config} */
export const config = {
runtime: 'edge'
};
about/+page.ts
ts
import type { Config } from '@sveltejs/adapter-vercel';
 
export const config: Config = {
runtime: 'edge',
};

...and others as Serverless Functions (note that by specifying config inside a layout, it applies to all child pages):

admin/+layout.js
ts
/** @type {import('@sveltejs/adapter-vercel').Config} */
export const config = {
runtime: 'nodejs18.x'
};
admin/+layout.ts
ts
import type { Config } from '@sveltejs/adapter-vercel';
 
export const config: Config = {
runtime: 'nodejs18.x',
};

The following options apply to all functions:

  • runtime: 'edge', 'nodejs16.x' or 'nodejs18.x'. By default, the adapter will select 'nodejs16.x' or 'nodejs18.x' depending on the Node version your project is configured to use on the Vercel dashboard
  • regions: an array of edge network regions (defaulting to ["iad1"] for serverless functions) or 'all' if runtime is edge (its default). Note that multiple regions for serverless functions are only supported on Enterprise plans
  • split: if true, causes a route to be deployed as an individual function. If split is set to true at the adapter level, all routes will be deployed as individual functions

Additionally, the following option applies to edge functions:

  • external: an array of dependencies that esbuild should treat as external when bundling functions. This should only be used to exclude optional dependencies that will not run outside Node

And the following option apply to serverless functions:

  • memory: the amount of memory available to the function. Defaults to 1024 Mb, and can be decreased to 128 Mb or increased in 64Mb increments up to 3008 Mb on Pro or Enterprise accounts
  • maxDuration: maximum execution duration of the function. Defaults to 10 seconds for Hobby accounts, 15 for Pro and 900 for Enterprise
  • isr: configuration Incremental Static Regeneration, described below

If your functions need to access data in a specific region, it's recommended that they be deployed in the same region (or close to it) for optimal performance.

Image Optimization

You may set the images config to control how Vercel builds your images. See the image configuration reference for full details. As an example, you may set:

{
	sizes: [640, 828, 1200, 1920, 3840],
	formats: ['image/avif', 'image/webp'],
	minimumCacheTTL: 300
}

Incremental Static Regeneration

Vercel supports Incremental Static Regeneration (ISR), which provides the performance and cost advantages of prerendered content with the flexibility of dynamically rendered content.

To add ISR to a route, include the isr property in your config object:

blog/[slug]/+page.server.js
ts
import { BYPASS_TOKEN } from '$env/static/private';
 
export const config = {
isr: {
// Expiration time (in seconds) before the cached asset will be re-generated by invoking the Serverless Function.
// Setting the value to `false` means it will never expire.
expiration: 60,
 
// Random token that can be provided in the URL to bypass the cached version of the asset, by requesting the asset
// with a __prerender_bypass=<token> cookie.
//
// Making a `GET` or `HEAD` request with `x-prerender-revalidate: <token>` will force the asset to be re-validated.
bypassToken: BYPASS_TOKEN,
 
// List of valid query parameters. Other parameters (such as utm tracking codes) will be ignored,
// ensuring that they do not result in content being regenerated unnecessarily
allowQuery: ['search']
}
};
blog/[slug]/+page.server.ts
ts
import { BYPASS_TOKEN } from '$env/static/private';
 
export const config = {
isr: {
// Expiration time (in seconds) before the cached asset will be re-generated by invoking the Serverless Function.
// Setting the value to `false` means it will never expire.
expiration: 60,
 
// Random token that can be provided in the URL to bypass the cached version of the asset, by requesting the asset
// with a __prerender_bypass=<token> cookie.
//
// Making a `GET` or `HEAD` request with `x-prerender-revalidate: <token>` will force the asset to be re-validated.
bypassToken: BYPASS_TOKEN,
 
// List of valid query parameters. Other parameters (such as utm tracking codes) will be ignored,
// ensuring that they do not result in content being regenerated unnecessarily
allowQuery: ['search'],
},
};

The expiration property is required; all others are optional.

Environment variables

Vercel makes a set of deployment-specific environment variables available. Like other environment variables, these are accessible from $env/static/private and $env/dynamic/private (sometimes — more on that later), and inaccessible from their public counterparts. To access one of these variables from the client:

+layout.server.js
ts
import { VERCEL_COMMIT_REF } from '$env/static/private';
 
/** @type {import('./$types').LayoutServerLoad} */
export function load() {
return {
deploymentGitBranch: VERCEL_COMMIT_REF
};
}
+layout.server.ts
ts
import { VERCEL_COMMIT_REF } from '$env/static/private';
import type { LayoutServerLoad } from './$types';
 
export const load: LayoutServerLoad = () => {
return {
deploymentGitBranch: VERCEL_COMMIT_REF,
};
};
+layout.svelte
<script>
  /** @type {import('./$types').LayoutServerData} */
  export let data;
</script>

<p>This staging environment was deployed from {data.deploymentGitBranch}.</p>
+layout.svelte
<script lang="ts">
  import type { LayoutServerData } from './$types';
  
  export let data: LayoutServerData;
</script>

<p>This staging environment was deployed from {data.deploymentGitBranch}.</p>

Since all of these variables are unchanged between build time and run time when building on Vercel, we recommend using $env/static/private — which will statically replace the variables, enabling optimisations like dead code elimination — rather than $env/dynamic/private.

Notes

Vercel functions

If you have Vercel functions contained in the api directory at the project's root, any requests for /api/* will not be handled by SvelteKit. You should implement these as API routes in your SvelteKit app instead, unless you need to use a non-JavaScript language in which case you will need to ensure that you don't have any /api/* routes in your SvelteKit app.

Node version

Projects created before a certain date will default to using Node 14, while SvelteKit requires Node 16 or later. You can change the Node version in your project settings.

Troubleshooting

Accessing the file system

You can't access the file system through methods like fs.readFileSync in Serverless/Edge environments. If you need to access files that way, do that during building the app through prerendering. If you have a blog for example and don't want to manage your content through a CMS, then you need to prerender the content (or prerender the endpoint from which you get it) and redeploy your blog everytime you add new content.