附录
迁移到 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 不再由你抛出永久链接
以前,你必须自己throw
从 error(...)
和 redirect(...)
返回的值。在 SvelteKit 2 中,不再需要这样做——调用这些函数就足够了。
import { error } from '@sveltejs/kit'
...
throw error(500, 'something went wrong');
error(500, 'something went wrong');
svelte-migrate
会自动为你执行这些更改。
如果错误或重定向在 try {...}
块内抛出(提示:不要这样做!),你可以使用从 @sveltejs/kit
导入的 isHttpError
和 isRedirect
将它们与意外错误区分开来。
设置 cookie 时路径是必需的永久链接
当收到未指定 path
的 Set-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 = url
。state
对象现在决定 $page.state
,并且必须遵守 App.PageState
接口(如果已声明)。有关更多详细信息,请参阅 浅层路由。
路径现在默认是相对路径永久链接
在 SvelteKit 1 中,app.html
中的 %sveltekit.assets%
在服务器端渲染期间默认替换为相对路径(即 .
或 ..
或 ../..
等,具体取决于正在渲染的路径),除非 paths.relative
配置选项明确设置为 false
。从 $app/paths
导入的 base
和 assets
也是如此,但前提是 paths.relative
选项明确设置为 true
。
此不一致性在版本 2 中已修复。路径要么始终是相对路径,要么始终是绝对路径,具体取决于 paths.relative
的值。它默认为 true
,因为这会导致更便携的应用程序:如果 base
是应用程序预期的内容以外的内容(例如,在 互联网档案 上查看时),或者在构建时未知(例如,部署到 IPFS 等),则不太可能出现故障。
服务器获取不再可跟踪永久链接
以前,可以从服务器上的 fetch
跟踪 URL 以重新运行加载函数。这会带来潜在的安全风险(泄露私有 URL),因此它位于 dangerZone.trackServerFetches
设置后面,该设置现已移除。
preloadCode
参数必须以 base 为前缀永久链接
SvelteKit 公开了两个函数,preloadCode
和 preloadData
,用于以编程方式加载与特定路径关联的代码和数据。在版本 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
钩子来清理此问题:status
和 message
。对于从你的代码(或你的代码调用的库代码)引发的错误,状态将为 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 中,这些属性包括 form
和 data
。它们在一段时间前已被弃用,取而代之的是 formElement
和 formData
,并且在 SvelteKit 2 中已被完全移除。
包含文件输入的表单必须使用 multipart/form-data永久链接
如果表单包含 <input type="file">
但没有 enctype="multipart/form-data"
属性,则非 JS 提交将省略该文件。如果 SvelteKit 2 在 use:enhance
提交期间遇到这样的表单,它将抛出一个错误,以确保你的表单在没有 JavaScript 时也能正常工作。
生成的 tsconfig.json 更加严格永久链接
以前,生成的 tsconfig.json
尽力在你的 tsconfig.json
包含 paths
或 baseUrl
时仍然生成一个有效的配置。在 SvelteKit 2 中,验证更加严格,并且在你 tsconfig.json
中使用 paths
或 baseUrl
时会发出警告。这些设置用于生成路径别名,你应该改用 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
将为你执行此操作)。