LabHub

博客

解读 SvelteKit 3.0 预发布版 — 会破坏什么、收紧了哪些默认值,以及还有哪些仍是 experimental

한국어English日本語中文

引言 — 没有发布公告,先悄悄上了 npm

svelte.dev 博客上还没有出现过「介绍 SvelteKit 3」这样的文章。但 npm 注册表上的痕迹已经很清楚了 —— @sveltejs/kit3.0.0-next.0在 2026 年 6 月 5 日上线,截至本文撰写时(2026-07-17),最新的预发布版本是 7 月 14 日的3.0.0-next.8。不到六周的时间里出了九个预发布版本,和稳定版2.69.3(7 月 13 日)并行沿着两条轨道发布。

仓库那边的证据也指向同一个方向。sveltejs/kit开着一个version-3分支,3.0 里程碑截至今天显示已关闭 107 个 issue、还有 27 个未关闭。正式发布日期尚未公布 —— 所以本文的内容也应当被当作「next.8 时刻的快照」来读。既然是预发布版,从现在起还可能继续变化。

但把version-3分支的更新日志从 next.0 通读到 next.8,有一件事会变得很清楚:这个大版本里几乎没有新功能。取而代之的是清偿两年积累下来的废弃预告、拉高工具链的地基、收紧默认值。而社区期待中理应作为 SvelteKit 3 门面的那些东西 —— remote functions、组件内的await —— 在 v3 预发布版里依然是 experimental。理解这个格局,就理解了迁移判断的一半。

时间线 — 先看看 2.x 已经跑到了哪里

要读懂 v3,得先了解 2.x 后期的脉络。以下日期均以 npm 注册表上的发布时刻为准。

2024-12-16  kit 2.12   新增 $app/state(基于 rune —— $app/stores 的继任者)
2025-07-14  svelte 5.36  组件 await(experimental.async 标记)
2025-07-24  kit 2.26   $app/paths 新增 resolve()/asset()(取代旧的 base/assets)
2025-07-31  kit 2.27   remote functions(experimental 标记)
2026-01-22  svelte 5.48  ← 后来成为 kit v3 最低 Svelte 版本要求的那个发行版
2026-05-01  kit 2.59   新增 query.live(experimental)
2026-05-22  kit 2.61   query.live 改为异步可迭代对象,移除查询的 .run()(破坏性变更)
2026-06-02  kit 2.62   无需 svelte.config.js 即可向 Vite 插件传递配置
2026-06-04  kit 2.63   显式环境变量(experimental)
2026-06-05  kit 3.0.0-next.0  ← 预发布开始
2026-07-14  kit 3.0.0-next.8  ← 当前

有两点值得留意。第一,2.62 和 2.63 是 v3 发布前的「预告片」 —— 用7 月摘要的说法,把配置迁到vite.config和显式环境变量,二者都是作为「Kit 3 会这样做的预览」先落地到 2.x 里的。第二,正如 2.61 所展示的那样,带有 experimental 标签的功能即便在小版本发布里也在持续发生破坏性变更。移除.run()、修改requested(...)的签名,这类改动是以 semver 小版本的形式发布出来的 —— 一旦打开了这个标记,你就进入了 semver 保护不到的地带。

v3 拉高的地基 — 运行时与工具链的最低要求

以下是next.0 的更新日志钉死的最低要求。

更新日志给 Vite 8 要求列出的理由是「通过 Vite hook filter 实现更快的构建,以及使用 Vite environment API 的更强适配器」 —— 具体的构建时间数字目前没有任何公开数据,所以这里只记录这是项目自己的说法。

被删除的 API —— 清偿两年积累的废弃预告

以下是在 v3 中被移除或改名的东西。它们无一例外都是继任 API 早已在 2.x 里先落地的情况,所以几乎不存在「突然删除」这回事。

消失的东西继任者继任者落地的时间
整个$app/stores模块(#15499)$app/statekit 2.12(2024-12)
$app/paths里的baseassetsresolveRoute(#15507)resolve()asset()kit 2.26(2025-07)
invalidateAll(deprecated)(#16289)refreshAll(goto的选项里也适用)v3 next.8 新增
$app/environment改名为$app/env(别名保留,next.1)v3
$env/*四个模块显式环境变量($app/env/private$app/env/public)kit 2.63(experimental)
必须有svelte.config.js把配置传给 Vite 插件(#16007)kit 2.62 起可用
文件夹里的 param 文件单一的params.js/ts文件(#16189)v3
preloadStrategy选项恒为modulepreload + output.linkHeaderPreloadv3
CSRF 的checkOrigintrustedOrigins在 kit 2.x 里已经 deprecated
@sveltejs/kit/node/polyfills、给适配器用的createEntries无(移除)

有几点值得说明。

$app/stores的移除,是 rune 迁移画上的句号。Svelte 5 的 rune把 store 挤出局已经很久了,但 SvelteKit 的pagenavigatingupdated这几个 store,出于向后兼容一直被留着。继任者$app/state落地至今已经一年半,作为一次清偿,这个时机算是比较温和的。

invalidateAllrefreshAll 是一次词汇统一。读一读PR #16289就能看出意图 —— 在 remote functions 的世界里,刷新数据用的是query.refresh(),而这和 load 函数世界里「使无效」(invalidation)的说法已经分裂开来。refreshAll就是把这两者收拢到一个词下面的名字,顺带也把「让 load 函数总是重新执行」的选项一起整理了。需要留意的一点:refreshAll在 2.69.3 里并不存在。这是升级到 v3 时才要做的切换,不是今天就能做的事。

环境变量从模块魔法走向显式声明。文档的预告措辞很明确 —— 显式环境变量会成为 v3 的默认方式,而$env/*模块和$app/environment会被移除。新方式在src/env.ts里声明。

// src/env.ts —— 在 kit 2.63+ 上可以通过 experimental.explicitEnvironmentVariables 提前试用
import { defineEnvVars } from '@sveltejs/kit/hooks';

export const variables = defineEnvVars({
	API_KEY: {}, // 默认是 private —— 只能从 $app/env/private 导入
});

如果说过去$env/static/private是一个「靠导入位置来强制是否暴露」的巧妙机制,那么新方式则是把应用里存在的环境变量清单本身,连同类型一起,钉死在一个文件里。「光看代码看不出到底有哪些变量」这个问题消失了,但代价是每多一个变量,声明就要多一行。

悄悄改变的默认值 —— 安全方面居多

比起删除,这些改动更安静,但确实会改变行为。迁移里最耗时间的,通常就是这一类。

顺带一提,强制在 remote functions 的响应上加cache-control: private, no-store、让个性化的查询结果不会残留在共享缓存里的这个修复,其实不是 v3 才有的 —— 它已经在 2.65.2 里落地了。收紧安全相关默认值并不是 v3 独有的主题,而是最近这几个月一贯的方向。

依然是 experimental 的东西 —— v3 不是功能型大版本

这是本文里最重要的一节。

Remote functions 在 v3 里依然是 experimental。官方文档现在仍然写着「currently experimental… subject to change without notice」,并且要求kit.experimental.remoteFunctionscompilerOptions.experimental.async这两个标记同时打开。更能说明问题的是 v3 预发布版的方向 —— next.7 反而禁止了在不打开标记的情况下放置*.remote.ts/js文件(#16247,2026-07-07 合并)。如果稳定化已迫在眉睫,是不会出现这种改动的。从 2025 年 7 月以 2.27 发布至今将近一年,即便跨过了 v3 这个大版本,remote functions 依然没有 API 稳定性的承诺。

组件await也是同样的故事。 从 Svelte 5.36(2025-07-14)起,它就一直靠experimental.async标记才能使用,而文档明确写出了这个标记会在什么时候移除 —— "The experimental flag will be removed in Svelte 6."。而 Svelte 6 目前并不存在于 npm 上 —— 6.x 无论是正式版还是预发布版都从未发布过,svelte 的latest是 5.56.6(2026-07-16)。kit v3 的最低要求是 Svelte 5.48,这一点本身就概括了这个格局:SvelteKit 的大版本和 Svelte 的大版本,是两列各走各的火车。 编译器那边的 experimental 名单里,fork API(5.42)和 async SSR(5.39)也依然留在原地。

也有一次方向相反的「毕业」 —— OpenTelemetry 追踪在 next.7 里走出了 experimental 命名空间,成为正式 API(#16260)。

归纳一下,v3 的真实面貌是这样的:所有带话题性的功能都停留在 experimental 轨道上,同时搭载在 2.x 和 v3 里发布,而大版本号则被用来更换其下方的地基 —— 运行时、打包器、命名、默认值。「升到 v3,remote functions 就会稳定」这个期待,从目前的证据来看是站不住脚的。

与邻居的对照 —— 大版本在做的事情不一样

同一周里搅动 React 生态的新闻是React Compiler 的 Rust 移植,拿来对照挺有意思。React 正在为了消除手动 memoization 而从头搭建编译器基础设施 —— 而且还处在实验性的 WIP 阶段 —— 而 Svelte 从一开始编译器就是框架本身,没有这个阶段要走。取而代之的是,Svelte 这边的大版本被用来拉高打包器(rolldown)和运行时的地基。2026 年,这两个框架有一个共同点:把大版本级别的精力花在基础工程上,而不是「新功能大放送」,而且都不会在短期内大幅改变应用开发者的代码。

那么,现在该做什么

今天在 2.x 上就能提前做的事 —— 这些全都是对 v3 迁移的预付款。

不应该做的事。

如果你是适配器或库的作者,要做的事情更多。createEntries没了,适配器将能够直接提供 Vite 插件(#16206),适配器体系也会围绕 Vite environment API 重新组织。相比应用代码,这一层生态更有可能是 v3 发布时真正的瓶颈所在。

结语

SvelteKit 3.0 预发布版的更新日志并不炫目。我认为这是个好信号。它不是那种要求你重新学习的大版本 —— 路由变了、数据加载模型变了那种 —— 而是一个履行废弃预告、拉高地基、收紧默认值的大版本。你不需要重新学 rune,也不需要重写 load 函数。

但期望值需要摆得非常准。remote functions 和组件await「转正」这件事,不会发生在 SvelteKit 3 上 —— 前者还没有时间表,后者按文档说是 Svelte 6 才会发生的事。把 v3 理解为「铺设那个未来所要立足的地基」(基于 rolldown 的 Vite 8、Node 22、清理干净的 API 表面)的一次发布,是和更新日志相吻合的读法。由于预发布仍在进行中,正式发布时本文的一些细节可能已经变化 —— 这是一份写在前提下的快照,前提是届时还会再核实一次。

参考资料

评论

还没有评论。

登录后即可发表评论