跳至主要内容

附录

迁移到 SvelteKit v2

在 GitHub 上编辑此页面

从 SvelteKit 版本 1 升级到版本 2 应该基本无缝。有一些重大更改需要注意,如下所列。你可以使用 npx svelte-migrate@latest sveltekit-2 自动迁移其中一些更改。

我们强烈建议在升级到 2.0 之前升级到最新的 1.x 版本,以便你可以利用有针对性的弃用警告。我们还建议首先更新到 Svelte 4:SvelteKit 1.x 的更高版本支持它,而 SvelteKit 2.0 要求它。

redirect 和 error 不再由你抛出

以前,你必须自己throwerror(...)redirect(...)返回的值。在 SvelteKit 2 中,不再需要这样做——调用这些函数就足够了。

import { error } from '@sveltejs/kit'

...
 throw error(500, 'something went wrong');
 error(500, 'something went wrong');

svelte-migrate会自动为你执行这些更改。

如果错误或重定向在 try {...}块内抛出(提示:不要这样做!),你可以使用从 @sveltejs/kit导入的 isHttpErrorisRedirect 将它们与意外错误区分开来。

设置 cookie 时路径是必需的

当收到未指定 pathSet-Cookie 头时,浏览器将 设置 cookie 路径 为相关资源的父级。此行为并不特别有用或直观,并且经常导致 bug,因为开发人员希望 cookie 适用于整个域。

从 SvelteKit 2.0 开始,您需要在调用 cookies.set(...)cookies.delete(...)cookies.serialize(...) 时设置 path,以便消除歧义。大多数情况下,您可能希望使用 path: '/',但您可以将其设置为任何您喜欢的内容,包括相对路径——'' 表示“当前路径”,'.' 表示“当前目录”。

export function load({ cookies }) {
	cookies.set(name, value);
	cookies.set(name, value, { path: '/' });
	return { response }
}

svelte-migrate 将添加注释,突出显示需要调整的位置。

不再等待顶级 Promise

在 SvelteKit 1 版本中,如果从 load 函数返回的对象的顶级属性是 Promise,则会自动等待它们。随着 流式传输 的引入,此行为变得有些尴尬,因为它迫使您将流式传输数据嵌套一层深。

从 2 版本开始,SvelteKit 不再区分顶级和非顶级 Promise。要恢复阻塞行为,请使用 await(在适当的情况下使用 Promise.all 来防止瀑布)。

// If you have a single promise
export function load({ fetch }) {
	const response = fetch(...).then(r => r.json());
	const response = await fetch(...).then(r => r.json());
	return { response }
}
// If you have multiple promises
export function load({ fetch }) {
	const a = fetch(...).then(r => r.json());
	const b = fetch(...).then(r => r.json());
	const [a, b] = await Promise.all([
	  fetch(...).then(r => r.json()),
	  fetch(...).then(r => r.json()),
	]);
	return { a, b };
}

goto(...) 更改

goto(...) 不再接受外部 URL。要导航到外部 URL,请使用 window.location.href = urlstate 对象现在决定 $page.state,并且必须遵守 App.PageState 接口(如果已声明)。有关更多详细信息,请参阅 浅层路由

路径现在默认是相对路径

在 SvelteKit 1 中,app.html 中的 %sveltekit.assets% 在服务器端渲染期间默认替换为相对路径(即 ...../.. 等,具体取决于正在渲染的路径),除非 paths.relative 配置选项明确设置为 false。从 $app/paths 导入的 baseassets 也是如此,但前提是 paths.relative 选项明确设置为 true

此不一致性在版本 2 中已修复。路径要么始终是相对路径,要么始终是绝对路径,具体取决于 paths.relative 的值。它默认为 true,因为这会导致更便携的应用程序:如果 base 是应用程序预期的内容以外的内容(例如,在 互联网档案 上查看时),或者在构建时未知(例如,部署到 IPFS 等),则不太可能出现故障。

服务器获取不再可跟踪

以前,可以从服务器上的 fetch 跟踪 URL 以重新运行加载函数。这会带来潜在的安全风险(泄露私有 URL),因此它位于 dangerZone.trackServerFetches 设置后面,该设置现已移除。

preloadCode 参数必须以 base 为前缀

SvelteKit 公开了两个函数,preloadCodepreloadData,用于以编程方式加载与特定路径关联的代码和数据。在版本 1 中,存在一个细微的不一致——传递给 preloadCode 的路径不需要以 base 路径为前缀(如果已设置),而传递给 preloadData 的路径则需要。

这在 SvelteKit 2 中已修复——在这两种情况下,如果设置了 base,则路径应以 base 为前缀。

此外,preloadCode 现在接受一个参数,而不是 n 个参数。

已移除 resolvePath

SvelteKit 1 包含一个名为 resolvePath 的函数,它允许你解析路由 ID(如 /blog/[slug])和一组参数(如 { slug: 'hello' })为路径名。遗憾的是,返回值不包含 base 路径,这限制了它在设置了 base 的情况下的用处。

因此,SvelteKit 2 用一个(命名稍好一些的)函数 resolveRoute 替换了 resolvePath,该函数从 $app/paths 导入,并考虑了 base

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 会为你执行方法替换,但如果你稍后使用 base 预置结果,则需要自己将其移除。

改进的错误处理

SvelteKit 1 中错误处理不一致。一些错误会触发 handleError 钩子,但没有好的方法来辨别它们的状态(例如,判断 404 和 500 的唯一方法是查看 event.route.id 是否为 null),而另一些错误(例如对没有操作的页面的 POST 请求的 405 错误)根本不会触发 handleError,但应该触发。在后一种情况下,如果指定了,则生成的 $page.error 将偏离 App.Error 类型。

SvelteKit 2 通过使用两个新属性调用 handleError 钩子来清理此问题:statusmessage。对于从你的代码(或你的代码调用的库代码)引发的错误,状态将为 500,消息将为 Internal Error。虽然 error.message 可能包含不应向用户公开的敏感信息,但 message 是安全的。

预渲染期间无法使用动态环境变量

$env/dynamic/public$env/dynamic/private 模块提供对运行时环境变量的访问,而不是 $env/static/public$env/static/private 公开的构建时环境变量。

在 SvelteKit 1 中的预渲染期间,它们是相同的。因此,使用“动态”环境变量的预渲染页面实际上是“烘焙”构建时值,这是不正确的。更糟糕的是,如果用户在导航到动态渲染页面之前碰巧进入预渲染页面,那么 $env/dynamic/public 会使用这些陈旧的值填充到浏览器中。

因此,在 SvelteKit 2 中的预渲染期间不能再读取动态环境变量——你应该改用 static 模块。如果用户进入预渲染页面,SvelteKit 将从服务器请求 $env/dynamic/public 的最新值(默认情况下,从名为 _env.js 的模块中——这可以通过 config.kit.env.publicModule 进行配置),而不是从服务器渲染的 HTML 中读取它们。

表单和数据已从 use:enhance 回调中移除

如果你为 use:enhance 提供回调,它将使用包含各种有用属性的对象进行调用。

在 SvelteKit 1 中,这些属性包括 formdata。它们在一段时间前已被弃用,取而代之的是 formElementformData,并且在 SvelteKit 2 中已被完全移除。

包含文件输入的表单必须使用 multipart/form-data

如果表单包含 <input type="file"> 但没有 enctype="multipart/form-data" 属性,则非 JS 提交将省略该文件。如果 SvelteKit 2 在 use:enhance 提交期间遇到这样的表单,它将抛出一个错误,以确保你的表单在没有 JavaScript 时也能正常工作。

生成的 tsconfig.json 更加严格

以前,生成的 tsconfig.json 尽力在你的 tsconfig.json 包含 pathsbaseUrl 时仍然生成一个有效的配置。在 SvelteKit 2 中,验证更加严格,并且在你 tsconfig.json 中使用 pathsbaseUrl 时会发出警告。这些设置用于生成路径别名,你应该改用 svelte.config.js 中的 alias 配置 选项,以便也为捆绑器创建相应的别名。

getRequest 不再引发错误

@sveltejs/kit/node 模块导出了用于在 Node 环境中使用的帮助器函数,包括 getRequest,它将 Node ClientRequest 转换为标准 Request 对象。

在 SvelteKit 1 中,如果 Content-Length 头部超出了指定的大小限制,则 getRequest 可能会引发错误。在 SvelteKit 2 中,该错误不会被立即引发,而是在读取请求正文(如果有的话)时才引发。这可以实现更好的诊断和更简单的代码。

vitePreprocess 不再从 @sveltejs/kit/vite 导出

由于 @sveltejs/vite-plugin-svelte 现在是一个对等依赖项,因此 SvelteKit 2 不再重新导出 vitePreprocess。你应该直接从 @sveltejs/vite-plugin-svelte 导入它。

更新的依赖项要求

SvelteKit 2 需要 Node 18.13 或更高版本,以及以下最低依赖项版本

  • svelte@4
  • vite@5
  • typescript@5
  • @sveltejs/vite-plugin-svelte@3(这现在是 SvelteKit 的 peerDependency 要求——以前它直接依赖)
  • @sveltejs/adapter-cloudflare@3(如果你正在使用这些适配器)
  • @sveltejs/adapter-cloudflare-workers@2
  • @sveltejs/adapter-netlify@3
  • @sveltejs/adapter-node@2
  • @sveltejs/adapter-static@3
  • @sveltejs/adapter-vercel@4

svelte-migrate 将为你更新 package.json

作为 TypeScript 升级的一部分,生成的 tsconfig.json(你的 tsconfig.json 从中扩展)现在使用 "moduleResolution": "bundler"(TypeScript 团队推荐,因为它可以正确解析具有 package.json 中 exports 映射的包中的类型)和 verbatimModuleSyntax(它替换了现有的 importsNotUsedAsValues preserveValueImports 标志——如果你在 tsconfig.json 中有这些标志,请删除它们。svelte-migrate 将为你执行此操作)。

上一个 集成