Skip to main content

迁移到 SvelteKit v2

从 SvelteKit 版本 1 升级到版本 2 应该基本无缝。需要注意一些重大更改,此处列出。你可以使用 npx sv migrate sveltekit-2 自动迁移其中一些更改。

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

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

¥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 first: Later versions of SvelteKit 1.x support it, and SvelteKit 2.0 requires it.

redirect 和 error 不再由你抛出(redirect and error are no longer thrown by you)

¥redirect and error are no longer thrown by you

以前,你必须自己对从 error(...)redirect(...) 返回的值进行 throw 处理。在 SvelteKit 2 中,情况不再如此 - 调用函数就足够了。

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

import { function error(status: number, body: App.Error): never (+1 overload)

Throws an error with a HTTP status code and an optional message. When called during request handling, this will cause SvelteKit to return an error response without invoking handleError. Make sure you’re not catching the thrown error, which would prevent SvelteKit from handling it.

@paramstatus The HTTP status code. Must be in the range 400-599.
@parambody An object that conforms to the App.Error type. If a string is passed, it will be used as the message property.
@throwsHttpError This error instructs SvelteKit to initiate HTTP error handling.
@throwsError If the provided status is invalid (not between 400 and 599).
error
} from '@sveltejs/kit'
// ... throw error(500, 'something went wrong');
function error(status: number, body?: {
    message: string;
} extends App.Error ? App.Error | string | undefined : never): never (+1 overload)

Throws an error with a HTTP status code and an optional message. When called during request handling, this will cause SvelteKit to return an error response without invoking handleError. Make sure you’re not catching the thrown error, which would prevent SvelteKit from handling it.

@paramstatus The HTTP status code. Must be in the range 400-599.
@parambody An object that conforms to the App.Error type. If a string is passed, it will be used as the message property.
@throwsHttpError This error instructs SvelteKit to initiate HTTP error handling.
@throwsError If the provided status is invalid (not between 400 and 599).
error
(500, 'something went wrong');

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

¥svelte-migrate will do these changes automatically for you.

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

¥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 and isRedirect imported from @sveltejs/kit.

¥path is required when setting cookies

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

¥When receiving a Set-Cookie header that doesn’t specify a path, browsers will set the cookie path 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.

从 SvelteKit 2.0 开始,你需要在调用 cookies.set(...)cookies.delete(...)cookies.serialize(...) 时设置 path,以免产生歧义。大多数时候,你可能想使用 path: '/',但你可以将其设置为你喜欢的任何值,包括相对路径 — '' 表示 ‘当前路径’,'.' 表示 ‘当前路径’。

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

/** @type {import('./$types').PageServerLoad} */
export function 
function load({ cookies }: {
    cookies: any;
}): {
    response: any;
}
@type{import('./$types').PageServerLoad}
load
({ cookies: anycookies }) {
cookies: anycookies.set(const name: void
@deprecated
name
, value, { path: stringpath: '/' });
return { response: anyresponse } }

svelte-migrate 将添加注释,高亮需要调整的位置。

¥svelte-migrate will add comments highlighting the locations that need to be adjusted.

不再等待顶层 promise(Top-level promises are no longer awaited)

¥Top-level promises are no longer awaited

在 SvelteKit 版本 1 中,如果从 load 函数返回的对象的顶层属性是 promise,则会自动等待它们。随着 streaming 的引入,这种行为变得有点尴尬,因为它迫使你将流数据嵌套一层。

¥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 this behavior became a bit awkward as it forces you to nest your streamed data one level deep.

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

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

// If you have a single promise
/** @type {import('./$types').PageServerLoad} */
export async function function load(event: ServerLoadEvent<Record<string, any>, Record<string, any>, string | null>): MaybePromise<void | Record<string, any>>
@type{import('./$types').PageServerLoad}
load
({
fetch: {
    (input: RequestInfo | URL, init?: RequestInit): Promise<Response>;
    (input: string | URL | globalThis.Request, init?: RequestInit): Promise<Response>;
}

fetch is equivalent to the native fetch web API, with a few additional features:

  • It can be used to make credentialed requests on the server, as it inherits the cookie and authorization headers for the page request.
  • It can make relative requests on the server (ordinarily, fetch requires a URL with an origin when used in a server context).
  • Internal requests (e.g. for +server.js routes) go directly to the handler function when running on the server, without the overhead of an HTTP call.
  • During server-side rendering, the response will be captured and inlined into the rendered HTML by hooking into the text and json methods of the Response object. Note that headers will not be serialized, unless explicitly included via filterSerializedResponseHeaders
  • During hydration, the response will be read from the HTML, guaranteeing consistency and preventing an additional network request.

You can learn more about making credentialed requests with cookies here

fetch
}) {
const const response: anyresponse = await fetch: (input: string | URL | globalThis.Request, init?: RequestInit) => Promise<Response> (+1 overload)fetch(const url: stringurl).Promise<Response>.then<any, never>(onfulfilled?: ((value: Response) => any) | null | undefined, onrejected?: ((reason: any) => PromiseLike<never>) | null | undefined): Promise<any>

Attaches callbacks for the resolution and/or rejection of the Promise.

@paramonfulfilled The callback to execute when the Promise is resolved.
@paramonrejected The callback to execute when the Promise is rejected.
@returnsA Promise for the completion of which ever callback is executed.
then
(r: Responser => r: Responser.Body.json(): Promise<any>json());
return { response: anyresponse } }
// If you have multiple promises
/** @type {import('./$types').PageServerLoad} */
export async function function load(event: ServerLoadEvent<Record<string, any>, Record<string, any>, string | null>): MaybePromise<void | Record<string, any>>
@type{import('./$types').PageServerLoad}
load
({
fetch: {
    (input: RequestInfo | URL, init?: RequestInit): Promise<Response>;
    (input: string | URL | globalThis.Request, init?: RequestInit): Promise<Response>;
}

fetch is equivalent to the native fetch web API, with a few additional features:

  • It can be used to make credentialed requests on the server, as it inherits the cookie and authorization headers for the page request.
  • It can make relative requests on the server (ordinarily, fetch requires a URL with an origin when used in a server context).
  • Internal requests (e.g. for +server.js routes) go directly to the handler function when running on the server, without the overhead of an HTTP call.
  • During server-side rendering, the response will be captured and inlined into the rendered HTML by hooking into the text and json methods of the Response object. Note that headers will not be serialized, unless explicitly included via filterSerializedResponseHeaders
  • During hydration, the response will be read from the HTML, guaranteeing consistency and preventing an additional network request.

You can learn more about making credentialed requests with cookies here

fetch
}) {
const a = fetch(url1).then(r => r.json()); const b = fetch(url2).then(r => r.json()); const [const a: anya, const b: anyb] = await var Promise: PromiseConstructor

Represents the completion of an asynchronous operation

Promise
.PromiseConstructor.all<[Promise<any>, Promise<any>]>(values: [Promise<any>, Promise<any>]): Promise<[any, any]> (+1 overload)

Creates a Promise that is resolved with an array of results when all of the provided Promises resolve, or rejected when any Promise is rejected.

@paramvalues An array of Promises.
@returnsA new Promise.
all
([
fetch: (input: string | URL | globalThis.Request, init?: RequestInit) => Promise<Response> (+1 overload)fetch(const url1: stringurl1).Promise<Response>.then<any, never>(onfulfilled?: ((value: Response) => any) | null | undefined, onrejected?: ((reason: any) => PromiseLike<never>) | null | undefined): Promise<any>

Attaches callbacks for the resolution and/or rejection of the Promise.

@paramonfulfilled The callback to execute when the Promise is resolved.
@paramonrejected The callback to execute when the Promise is rejected.
@returnsA Promise for the completion of which ever callback is executed.
then
(r: Responser => r: Responser.Body.json(): Promise<any>json()),
fetch: (input: string | URL | globalThis.Request, init?: RequestInit) => Promise<Response> (+1 overload)fetch(const url2: stringurl2).Promise<Response>.then<any, never>(onfulfilled?: ((value: Response) => any) | null | undefined, onrejected?: ((reason: any) => PromiseLike<never>) | null | undefined): Promise<any>

Attaches callbacks for the resolution and/or rejection of the Promise.

@paramonfulfilled The callback to execute when the Promise is resolved.
@paramonrejected The callback to execute when the Promise is rejected.
@returnsA Promise for the completion of which ever callback is executed.
then
(r: Responser => r: Responser.Body.json(): Promise<any>json()),
]); return { a: anya, b: anyb }; }

goto(...) 更改(goto(...) changes)

¥goto(...) changes

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

¥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 for more details.

路径现在默认是相对的(paths are now relative by default)

¥paths are now relative by default

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

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

此不一致问题已在版本 2 中修复。路径始终是相对的或始终是绝对的,具体取决于 paths.relative 的值。它默认为 true,因为这会产生更多可移植的应用:如果 base 不是应用预期的内容(例如,在 Internet Archive 上查看时的情况)或在构建时未知(例如,在部署到 IPFS 等时的情况),则发生故障的可能性较小。

¥This inconsistency is fixed in version 2. Paths are either always relative or always absolute, depending on the value of paths.relative. 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, for example) or unknown at build time (as is the case when deploying to IPFS and so on), fewer things are likely to break.

服务器获取不再可跟踪(Server fetches are not trackable anymore)

¥Server fetches are not trackable anymore

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

¥Previously it was possible to track URLs from fetches 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 参数必须以 base 为前缀(preloadCode arguments must be prefixed with base)

¥preloadCode arguments must be prefixed with base

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

¥SvelteKit exposes two functions, preloadCode and 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.

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

¥This is fixed in SvelteKit 2 — in both cases, the path should be prefixed with base if it is set.

此外,preloadCode 现在采用单个参数而不是 n 个参数。

¥Additionally, preloadCode now takes a single argument rather than n arguments.

resolvePath 已被移除(resolvePath has been removed)

¥resolvePath has been removed

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

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

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

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

import { resolvePath } from '@sveltejs/kit';
import { base } from '$app/paths';
import { function resolveRoute(id: string, params: Record<string, string | undefined>): string

Populate a route ID with params to resolve a pathname.

@examplejs import { resolveRoute } from '$app/paths'; resolveRoute( `/blog/[slug]/[...somethingElse]`, { slug: 'hello-world', somethingElse: 'something/else' } ); // `/blog/hello-world/something/else`
resolveRoute
} from '$app/paths';
const path = base + resolvePath('/blog/[slug]', { slug }); const const path: stringpath = function resolveRoute(id: string, params: Record<string, string | undefined>): string

Populate a route ID with params to resolve a pathname.

@examplejs import { resolveRoute } from '$app/paths'; resolveRoute( `/blog/[slug]/[...somethingElse]`, { slug: 'hello-world', somethingElse: 'something/else' } ); // `/blog/hello-world/something/else`
resolveRoute
('/blog/[slug]', { slug: anyslug });

svelte-migrate 将为你执行方法替换,但如果你稍后在结果前面添加 base,则需要自行将其删除。

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

¥Improved error handling

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

¥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 type, if it is specified.

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

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

¥Dynamic environment variables cannot be used during prerendering

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

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

在 SvelteKit 1 的预渲染过程中,它们是同一个。因此,使用 ‘dynamic’ 环境变量的预渲染页面实际上是 ‘烘焙’ 构建时间值,这是不正确的。更糟糕的是,如果用户在导航到动态渲染的页面之前恰好登陆预渲染页面,浏览器中的 $env/dynamic/public 会填充这些过时的值。

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

因此,在 SvelteKit 2 中,在预渲染期间无法再读取动态环境变量 - 你应该改用 static 模块。如果用户进入预渲染页面,SvelteKit 将从服务器(默认情况下从名为 /_app/env.js 的模块)请求 $env/dynamic/public 的最新值,而不是从服务器渲染的 HTML 中读取它们。

¥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 和 data 已从 use:enhance 回调中移除(form and data have been removed from use:enhance callbacks)

¥form and data have been removed from use:enhance callbacks

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

¥If you provide a callback to use:enhance, it will be called with an object containing various useful properties.

在 SvelteKit 1 中,这些属性包括 formdata。这些在不久前被弃用,取而代之的是 formElementformData,并且在 SvelteKit 2 中被全部删除。

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

包含文件输入的表单必须使用 multipart/form-data(Forms containing file inputs must use multipart/form-data)

¥Forms containing file inputs must use multipart/form-data

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

¥If a form contains an <input type="file"> 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.

生成的 tsconfig.json 更严格(Generated tsconfig.json is more strict)

¥Generated tsconfig.json is more strict

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

¥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 option in your svelte.config.js instead, to also create a corresponding alias for the bundler.

getRequest 不再抛出错误(getRequest no longer throws errors)

¥getRequest no longer throws errors

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

¥The @sveltejs/kit/node module exports helper functions for use in Node environments, including getRequest which turns a Node ClientRequest into a standard Request object.

在 SvelteKit 1 中,如果 Content-Length 标头超出指定的大小限制,则 getRequest 可能会抛出。在 SvelteKit 2 中,直到稍后读取请求主体(如果有)时才会抛出错误。这可以实现更好的诊断和更简单的代码。

¥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 不再从 @sveltejs/kit/vite 导出(vitePreprocess is no longer exported from @sveltejs/kit/vite)

¥vitePreprocess is no longer exported from @sveltejs/kit/vite

由于 @sveltejs/vite-plugin-svelte 现在是同级依赖,SvelteKit 2 不再重新导出 vitePreprocess。你应该直接从 @sveltejs/vite-plugin-svelte 导入它。

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

¥Updated dependency requirements

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

¥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(现在需要将其作为 SvelteKit 的 peerDependency — 以前它直接依赖于此)

    ¥@sveltejs/vite-plugin-svelte@3 (this is now required as a peerDependency of SvelteKit — previously it was directly depended upon)

  • @sveltejs/adapter-cloudflare@3(如果你使用这些适配器)

    ¥@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 将为你更新你的 package.json

¥svelte-migrate will update your package.json for you.

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

¥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 已弃用(SvelteKit 2.12: $app/stores deprecated)

¥SvelteKit 2.12: $app/stores deprecated

SvelteKit 2.12 在 Svelte 5 符文 API 的基础上引入了 $app/state$app/state 提供 $app/stores 提供的所有内容,但在使用位置和方式方面具有更大的灵活性。最重要的是,page 对象现在是细粒度的,例如对 page.state 的更新不会使 page.data 无效,反之亦然。

¥SvelteKit 2.12 introduced $app/state based on the Svelte 5 runes API. $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.

因此,$app/stores 已弃用,并将在 SvelteKit 3 中删除。如果你还没有使用 升级至 Svelte 5,我们建议你使用,然后从 $app/stores 迁移出去。大多数替换应该非常简单:将 $app/stores 导入替换为 $app/state,并从使用站点中删除 $ 前缀。

¥As a consequence, $app/stores is deprecated and subject to be removed in SvelteKit 3. We recommend upgrading to Svelte 5, 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.

<script>
	import { page } from '$app/stores';
	import { page } from '$app/state';
</script>

{$page.data}
{page.data}

使用 npx sv migrate app-state 自动迁移 .svelte 组件内的大部分 $app/stores 用法。

¥Use npx sv migrate app-state to auto-migrate most of your $app/stores usages inside .svelte components.

上一页 下一页