SvelteKit 3 进 RC:svelte.config.js 这个文件直接没了,$lib 改名 #lib——13 个破坏性变更锁定,升级窗口就是现在
SvelteKit 3 进 RC 了:svelte.config.js 这个文件直接没了,$lib 也改了名,Node 22 / TS 6 / Vite 8 三座门槛一起抬高——13 个破坏性变更已经锁定,升级窗口就是现在。
先给结论:这不是一次常规小版本,SvelteKit 3 是一次真正的大版本,而且是近几年前端框架里少见的”连迁移工具都一起给你了”的大版本。 Svelte 团队 8 月 13 日把 Kit 3 推到了 Release Candidate,意味着破坏性变更已经冻结,接下来只接受 bug 修复,stable 就在”数周之后”,不会再有新惊喜。对还在跑 SvelteKit 2 的项目来说,现在是从容迁移的窗口,而不是等着 stable 发布时被动救火。
三个会影响几乎所有项目的改动
第一,svelte.config.js 被删掉了。
以后所有配置都写进 vite.config.ts 里的 sveltekit() 插件调用。官方的理由是:异步解析配置太绕了,而且配置本来就该在一个地方,不是两个。
// 旧:svelte.config.js
import adapter from '@sveltejs/adapter-auto';
export default { kit: { adapter: adapter() } };
// 新:vite.config.js
import { sveltekit } from '@sveltejs/vite-plugin-svelte';
export default {
plugins: [sveltekit({ adapter: adapter() })]
};
迁移是机械的:把导出的对象搬进插件参数,删掉旧文件,收工。
第二,$lib 换成了 #lib。
SvelteKit 2 里 $lib 别名指向 src/lib,这比 ../../../../somewhere 好看多了。但 SvelteKit 3 直接把它换成了 Node 原生的 subpath imports——也就是 package.json 里声明、Vite 和 TypeScript 都能原生解析的 #lib。好处是 SvelteKit 自己不用再维护一套协调代码了。
代价是一个小坑:Node 和 TypeScript 要求 subpath 导入必须无歧义,所以 #lib/foo 这种写法不行,得写成 #lib/foo.ts 或 #lib/foo/index.ts——必须带扩展名。
"imports": {
"#lib": "./src/lib/index.js",
"#lib/": "./src/lib/"
}
*第三,`$env/` 系列整体变成”显式环境变量”。**
$env/static/public、$env/dynamic/private、$app/environment 全都被标注为弃用,换成了在 src/env.ts 里统一声明的新体系。你要显式说明每个变量是 public 还是 private、是 build time 解析还是运行时解析,甚至可以用 Standard Schema 做校验。
// src/env.ts
import { defineEnvVars } from '@sveltejs/kit/env';
export const variables = defineEnvVars({
PUBLIC_API_URL: { public: true, buildTime: true },
DB_PASSWORD: { public: false, buildTime: false }
});
换来的是:类型安全、可校验、build-time 变量能做 dead code elimination(直接摇掉),而且 import 时会自动补全。
顺手被清理掉的那些历史包袱
除了上面三个主线改动,这次还砍掉了一批让人翻旧文档才能理解的东西:
$app/stores没了,page/navigating/updated全搬到$app/state,基于 Svelte 5 runes 重写——用的时候记得把$前缀去掉。$service-worker模块没了,替代品是$app/manifest和$app/service-worker,service worker 终于有正经类型了。tsconfig.json不用再 extend 那个丑丑的./.svelte-kit/tsconfig.json,改成 extend$app/tsconfig,而且里面塞了更多推荐配置,多数项目可以把自定义的compilerOptions删掉。- 错误处理大改:SvelteKit 2 受制于要兼容 Svelte 4(没有 error boundary 概念),只能在 load 出错时显示
+error.svelte。Kit 3 强制 Svelte 5,渲染期错误也能接住;而且你主动error(...)抛出的错误现在也会过一遍handleError——以前会被忽略,因为它假定你已经自己处理了。另外,堆栈开始应用 sourcemap 了。 - 浅路由换 API:从
pushState/replaceState换成goto(..., { shallow: true }),而且浅导航现在会正常触发beforeNavigate,还能用persistState: true跨刷新保留页面状态。
门槛抬高了,Vite 8 是真正会卡住你的那一个
SvelteKit 3 不是”支持”了 Vite 8,而是要求 Vite 8。其他最低版本要求:
- Node.js v22.17+
- TypeScript v6+
- Svelte v5.56.4+
- Vite v8.0.12+
@sveltejs/vite-plugin-sveltev7+
Vite 8 自带 Rolldown 作为打包器——一个用 Rust 重写的、替代 esbuild + Rollup 的实现。构建确实快得多,但它破坏了和老插件的兼容性。所以迁移流程里最容易翻车的一步不是改代码,是:先审你的 Vite 插件清单,再动迁移。
现在该做什么
官方给了迁移工具,这一版 SvelteKit 罕见地把大版本升级的机械工作自动化了:
# 迁移已有项目
npx sv@next migrate sveltekit-3 --tasks all --confirm
# 新建项目
npx sv@next create my-new-app
它会把配置搬家、把 $lib 批量改成 #lib、迁移 $env 引用。搞不定的部分,它会生成一份带 @migration 标注的 TODO 清单,交给你的”clanker”(它原话)去逐条处理。跑不兼容的代码时,Kit 会打印诊断警告和错误,不会让你盲猜。
推荐顺序是:
- 先升到最新的 SvelteKit 2.x——它会打印一堆针对性的弃用警告,让你的 TODO 清单变短;
- 再跑迁移工具;
- 审一遍 Vite 8 插件兼容性;
- 最后拿 RC 冒烟测试(
npm i @sveltejs/kit@next)。
至于 Remote Functions——它是这一版真正的方向(query / command / form / prerender 四类,把客户端和服务端通信做成了类 tRPC 的 RPC 调用),但目前仍然带 experimental 标记,API 还可能变,别急着上生产。不过它在 RC 阶段已经够稳定,值得提前熟悉,因为 load function 那套模式确实在往后退。
一句话收尾:SvelteKit 3 的意义不是”又一个 breaking change”,而是它第一次连”怎么从 2 迁到 3″都替你想好了。 有迁移工具、有诊断警告、有 deprecated 预告,这种升级体验在前端框架里是稀缺品。窗口就摆在现在,等 stable 再动手,你只是在给自己制造截止日期。
评论区
登录后可评论。