Skip to main content

Vercel

要部署到 Vercel,请使用 adapter-vercel

¥To deploy to Vercel, use adapter-vercel.

当你使用 adapter-auto 时,此适配器将默认安装,但将其添加到你的项目中允许你指定特定于 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)

¥Usage

使用 npm i -D @sveltejs/adapter-vercel 安装,然后将适配器添加到你的 svelte.config.js

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

svelte.config
import function adapter(config?: Config): Adapteradapter from '@sveltejs/adapter-vercel';

export default {
	
kit: {
    adapter: Adapter;
}
kit
: {
adapter: Adapteradapter: function adapter(config?: Config): Adapteradapter({ // see below for options that can be set here }) } };

部署配置(Deployment configuration)

¥Deployment configuration

要控制如何将路由作为函数部署到 Vercel,你可以指定部署配置,方法是通过上面显示的选项,也可以使用 +server.js+page(.server).js+layout(.server).js 文件中的 export const config

¥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.

例如,你可以将应用的某些部分部署为 Edge 函数...

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

about/+page
/** @type {import('@sveltejs/adapter-vercel').Config} */
export const 
const config: {
    runtime: string;
}
@type{import('@sveltejs/adapter-vercel').Config}
config
= {
runtime: stringruntime: 'edge' };
import type { 
type Config = (EdgeConfig | ServerlessConfig) & {
    images?: ImagesConfig;
}
Config
} from '@sveltejs/adapter-vercel';
export const const config: Configconfig:
type Config = (EdgeConfig | ServerlessConfig) & {
    images?: ImagesConfig;
}
Config
= {
runtime: "edge"runtime: 'edge' };

...和其他作为 无服务器功能(请注意,通过在布局中指定 config,它将应用于所有子页面):

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

admin/+layout
/** @type {import('@sveltejs/adapter-vercel').Config} */
export const 
const config: {
    runtime: string;
}
@type{import('@sveltejs/adapter-vercel').Config}
config
= {
runtime: stringruntime: 'nodejs22.x' };
import type { 
type Config = (EdgeConfig | ServerlessConfig) & {
    images?: ImagesConfig;
}
Config
} from '@sveltejs/adapter-vercel';
export const const config: Configconfig:
type Config = (EdgeConfig | ServerlessConfig) & {
    images?: ImagesConfig;
}
Config
= {
ServerlessConfig.runtime?: `nodejs${number}.x` | undefined

Whether to use Edge Functions ('edge') or Serverless Functions ('nodejs18.x', 'nodejs20.x' etc).

@defaultSame as the build environment
runtime
: 'nodejs22.x'
};

以下选项适用于所有函数:

¥The following options apply to all functions:

  • runtime'edge''nodejs18.x''nodejs20.x''nodejs22.x'。默认情况下,适配器将选择与你的项目在 Vercel 仪表板上配置使用的 Node 版本相对应的 'nodejs<version>.x'

    ¥runtime: 'edge', 'nodejs18.x', 'nodejs20.x' or 'nodejs22.x'. By default, the adapter will select the 'nodejs<version>.x' corresponding to the Node version your project is configured to use on the Vercel dashboard

  • regions边缘网络区域 数组(对于无服务器函数,默认为 ["iad1"])或 'all'(如果 runtimeedge,则为 runtime(其默认值)。请注意,无服务器功能的多个区域仅在企业计划中受支持

    ¥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:如果 true,则会导致路由作为单独的函数部署。如果在适配器级别将 split 设置为 true,则所有路由都将作为单独的函数部署

    ¥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:esbuild 在打包函数时应将其视为外部依赖的数组。这应该只用于排除不会在 Node 之外运行的可选依赖

    ¥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:函数可用的内存量。默认为 1024 Mb,并且可以以 64Mb 的增量减少到 128 Mb 或 increased,在 Pro 或 Enterprise 账户上最高可达 3008 Mb

    ¥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:函数的 最大执行时长。Hobby 账户默认为 10 秒,Pro 账户默认为 15,Enterprise 账户默认为 900

    ¥maxDuration: maximum execution duration of the function. Defaults to 10 seconds for Hobby accounts, 15 for Pro and 900 for Enterprise

  • isr:配置增量静态再生,如下所述

    ¥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)

¥Image Optimization

你可以设置 images 配置来控制 Vercel 如何构建你的图片。有关完整详细信息,请参阅 图片配置参考。例如,你可以设置:

¥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:

svelte.config
import function adapter(config?: Config): Adapteradapter from '@sveltejs/adapter-vercel';

export default {
	
kit: {
    adapter: Adapter;
}
kit
: {
adapter: Adapteradapter: function adapter(config?: Config): Adapteradapter({ images?: ImagesConfig | undefinedimages: { sizes: number[]sizes: [640, 828, 1200, 1920, 3840], formats?: ImageFormat[] | undefinedformats: ['image/avif', 'image/webp'], minimumCacheTTL?: number | undefinedminimumCacheTTL: 300, domains: string[]domains: ['example-app.vercel.app'], } }) } };

增量静态再生(Incremental Static Regeneration)

¥Incremental Static Regeneration

Vercel 支持 增量静态再生 (ISR),它提供了预渲染内容的性能和成本优势以及动态渲染内容的灵活性。

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

仅在每个访问者都应看到相同内容的路由上使用 ISR(就像你预渲染时一样)。如果发生任何用户特定的事情(例如会话 cookie),它们应该仅通过 JavaScript 在客户端上发生,以免在访问期间泄露敏感信息

¥Use ISR only on routes where every visitor should see the same content (much like when you prerender). If there’s anything user-specific happening (like session cookies), they should happen on the client via JavaScript only to not leak sensitive information across visits

要将 ISR 添加到路由,请在 config 对象中包含 isr 属性:

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

import { import BYPASS_TOKENBYPASS_TOKEN } from '$env/static/private';

export const 
const config: {
    isr: {
        expiration: number;
        bypassToken: any;
        allowQuery: string[];
    };
}
config
= {
isr: {
    expiration: number;
    bypassToken: any;
    allowQuery: string[];
}
isr
: {
expiration: numberexpiration: 60, bypassToken: anybypassToken: import BYPASS_TOKENBYPASS_TOKEN, allowQuery: string[]allowQuery: ['search'] } };

在带有 export const prerender = true 的路由上使用 ISR 不会产生任何影响,因为该路由是在构建时预渲染的

¥Using ISR on a route with export const prerender = true will have no effect, since the route is prerendered at build time

expiration 属性是必需的;其他所有都是可选的。下面将更详细地讨论这些属性。

¥The expiration property is required; all others are optional. The properties are discussed in more detail below.

expiration

通过调用无服务器函数重新生成缓存资源之前的到期时间(以秒为单位)。将值设置为 false 意味着它永不过期。在这种情况下,你可能希望定义一个旁路令牌以根据需要重新生成。

¥The 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. In that case, you likely want to define a bypass token to re-generate on demand.

bypassToken

可以在 URL 中提供的随机令牌,通过使用 __prerender_bypass=<token> cookie 请求资源来绕过资源的缓存版本。

¥A 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.

使用 x-prerender-revalidate: <token> 发出 GETHEAD 请求将强制重新验证资源。

¥Making a GET or HEAD request with x-prerender-revalidate: <token> will force the asset to be re-validated.

请注意,BYPASS_TOKEN 字符串必须至少有 32 个字符长。你可以使用 JavaScript 控制台生成一个,如下所示:

¥Note that the BYPASS_TOKEN string must be at least 32 characters long. You could generate one using the JavaScript console like so:

var crypto: Cryptocrypto.Crypto.randomUUID(): `${string}-${string}-${string}-${string}-${string}`

Available only in secure contexts.

MDN Reference

randomUUID
();

通过登录并转到你的项目,然后转到“设置”>“环境变量”,将此字符串设置为 Vercel 上的环境变量。对于 “键",输入 BYPASS_TOKEN,对于 “value”,使用上面生成的字符串,然后点击 “保存”。

¥Set this string as an environment variable on Vercel by logging in and going to your project then Settings > Environment Variables. For “Key” put BYPASS_TOKEN and for “value” use the string generated above, then hit “Save”.

要让此密钥为本地开发所知,你可以通过在本地运行 vercel env pull 命令来使用 Vercel CLI,如下所示:

¥To get this key known about for local development, you can use the Vercel CLI by running the vercel env pull command locally like so:

vercel env pull .env.development.local

allowQuery

对缓存键有贡献的有效查询参数列表。其他参数(例如 utm 跟踪代码)将被忽略,确保它们不会导致不必要地重新生成内容。默认情况下,查询参数将被忽略。

¥A list of valid query parameters that contribute to the cache key. Other parameters (such as utm tracking codes) will be ignored, ensuring that they do not result in content being re-generated unnecessarily. By default, query parameters are ignored.

prerendered 页面将忽略 ISR 配置。

¥Pages that are prerendered will ignore ISR configuration.

环境变量(Environment variables)

¥Environment variables

Vercel 提供一组 部署特定的环境变量。与其他环境变量一样,这些变量可以从 $env/static/private$env/dynamic/private 访问(有时 - 稍后会详细介绍),并且无法从其公共对应变量访问。要从客户端访问以下变量之一:

¥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
import { import VERCEL_COMMIT_REFVERCEL_COMMIT_REF } from '$env/static/private';

/** @type {import('./$types').LayoutServerLoad} */
export function 
function load(): {
    deploymentGitBranch: any;
}
@type{import('./$types').LayoutServerLoad}
load
() {
return { deploymentGitBranch: anydeploymentGitBranch: import VERCEL_COMMIT_REFVERCEL_COMMIT_REF }; }
import { import VERCEL_COMMIT_REFVERCEL_COMMIT_REF } from '$env/static/private';
import type { 
type LayoutServerLoad = (event: Kit.ServerLoadEvent<Record<string, any>, Record<string, any>, string | null>) => MaybePromise<void | Record<string, any>>
type LayoutServerLoad = (event: Kit.ServerLoadEvent<Record<string, any>, Record<string, any>, string | null>) => MaybePromise<void | Record<string, any>>
LayoutServerLoad
} from './$types';
export const const load: LayoutServerLoadload:
type LayoutServerLoad = (event: Kit.ServerLoadEvent<Record<string, any>, Record<string, any>, string | null>) => MaybePromise<void | Record<string, any>>
type LayoutServerLoad = (event: Kit.ServerLoadEvent<Record<string, any>, Record<string, any>, string | null>) => MaybePromise<void | Record<string, any>>
LayoutServerLoad
= () => {
return { deploymentGitBranch: anydeploymentGitBranch: import VERCEL_COMMIT_REFVERCEL_COMMIT_REF }; };
+layout
<script>
	/** @type {import('./$types').LayoutProps} */
	let { data } = $props();
</script>

<p>This staging environment was deployed from {data.deploymentGitBranch}.</p>
<script lang="ts">
	import type { LayoutProps } from './$types';

	let { data }: LayoutProps = $props();
</script>

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

由于在 Vercel 上构建时,所有这些变量在构建时和运行时之间都没有变化,我们建议使用 $env/static/private(它将静态替换变量,从而实现诸如死代码消除之类的优化)而不是 $env/dynamic/private

¥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.

倾斜保护(Skew protection)

¥Skew protection

部署应用的新版本时,属于先前版本的资源可能不再可访问。如果用户在发生这种情况时正在积极使用你的应用,则导航时可能会导致错误 - 这称为版本偏差。SvelteKit 通过检测版本偏差导致的错误并导致硬重新加载以获取应用的最新版本来缓解这种情况,但这会导致任何客户端状态丢失。(你还可以通过观察 updated 存储值来主动缓解它,它会告诉客户端何时部署了新版本。)

¥When a new version of your app is deployed, assets belonging to the previous version may no longer be accessible. If a user is actively using your app when this happens, it can cause errors when they navigate — this is known as version skew. SvelteKit mitigates this by detecting errors resulting from version skew and causing a hard reload to get the latest version of the app, but this will cause any client-side state to be lost. (You can also proactively mitigate it by observing the updated store value, which tells clients when a new version has been deployed.)

倾斜保护 是 Vercel 的一项功能,可将客户端请求路由到其原始部署。当用户访问你的应用时,会使用部署 ID 设置一个 cookie,只要倾斜保护处于活动状态,任何后续请求都将被路由到该部署。当他们重新加载页面时,他们将获得最新的部署。(updated 存储不受此限制行为,因此将继续报告新的部署。)要启用它,请访问 Vercel 上项目设置的高级部分。

¥Skew protection is a Vercel feature that routes client requests to their original deployment. When a user visits your app, a cookie is set with the deployment ID, and any subsequent requests will be routed to that deployment for as long as skew protection is active. When they reload the page, they will get the newest deployment. (The updated store is exempted from this behaviour, and so will continue to report new deployments.) To enable it, visit the Advanced section of your project settings on Vercel.

基于 Cookie 的倾斜保护有一个警告:如果用户在多个选项卡中打开了你的应用的多个版本,则来自旧版本的请求将被路由到较新的版本,这意味着它们将回退到 SvelteKit 的内置倾斜保护。

¥Cookie-based skew protection comes with one caveat: if a user has multiple versions of your app open in multiple tabs, requests from older versions will be routed to the newer one, meaning they will fall back to SvelteKit’s built-in skew protection.

注释(Notes)

¥Notes

Vercel 函数(Vercel functions)

¥Vercel functions

如果项目根目录中的 api 目录中包含 Vercel 函数,则 SvelteKit 不会处理对 /api/* 的任何请求。你应该在 SvelteKit 应用中将它们实现为 API 路由,除非你需要使用非 JavaScript 语言,在这种情况下你需要确保你的 SvelteKit 应用中没有任何 /api/* 路由。

¥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 版本(Node version)

¥Node version

在某个日期之前创建的项目可能默认使用比 SvelteKit 当前要求的更旧的 Node 版本。你可以 在项目设置中更改 Node 版本

¥Projects created before a certain date may default to using an older Node version than what SvelteKit currently requires. You can change the Node version in your project settings.

故障排除(Troubleshooting)

¥Troubleshooting

访问文件系统(Accessing the file system)

¥Accessing the file system

你不能在边缘函数中使用 fs

¥You can’t use fs in edge functions.

你可以在无服务器函数中使用它,但它不会按预期工作,因为文件不会从你的项目复制到你的部署中。相反,使用 $app/server 中的 read 函数来访问你的文件。read 不在作为边缘函数部署的路由内工作(未来可能会发生变化)。

¥You can use it in serverless functions, but it won’t work as expected, since files are not copied from your project into your deployment. Instead, use the read function from $app/server to access your files. read does not work inside routes deployed as edge functions (this may change in future).

或者,你可以 prerender 相关路由。

¥Alternatively, you can prerender the routes in question.

上一页 下一页