此迁移指南概述了如何从 Svelte 版本 3 迁移到版本 4。有关每个更改的更多详细信息,请参阅链接的 PR。使用迁移脚本自动迁移其中一些:npx svelte-migrate@latest svelte-4
如果您是库作者,请考虑仅支持 Svelte 4 或是否也可以支持 Svelte 3。由于大多数重大更改不会影响很多人,因此这可能很容易实现。此外,请记住在 peerDependencies
中更新版本范围。
最低版本要求永久链接
- 升级到 Node 16 或更高版本。不再支持较早版本。(#8566)
- 如果您正在使用 SvelteKit,请升级到 1.20.4 或更高版本 (sveltejs/kit#10172)
- 如果您在不使用 SvelteKit 的情况下使用 Vite,请升级到
vite-plugin-svelte
2.4.1 或更高版本 (#8516) - 如果您正在使用 webpack,请升级到 webpack 5 或更高版本以及
svelte-loader
3.1.8 或更高版本。不再支持较早版本。(#8515, 198dbcf) - 如果您正在使用 Rollup,请升级到
rollup-plugin-svelte
7.1.5 或更高版本 (198dbcf) - 如果您正在使用 TypeScript,请升级到 TypeScript 5 或更高版本。较低版本可能仍然有效,但对此不做任何保证。(#8488)
捆绑器的浏览器条件永久链接
捆绑器现在必须在为浏览器构建前端捆绑包时指定 browser
条件。SvelteKit 和 Vite 将自动为您处理此问题。如果您使用任何其他捆绑器,您可能会观察到生命周期回调(例如 onMount
)未被调用,并且您需要更新模块解析配置。
- 对于 Rollup,这是通过在
@rollup/plugin-node-resolve
插件中设置browser: true
来完成的。有关更多详细信息,请参阅rollup-plugin-svelte
文档 - 对于 webpack,这是通过将
"browser"
添加到conditionNames
数组来完成的。如果您已设置别名配置,您可能还必须更新它。有关更多详细信息,请参阅svelte-loader
文档
(#8516)
删除与 CJS 相关的输出永久链接
Svelte 不再支持编译器输出的 CommonJS (CJS) 格式,并且还移除了 svelte/register
钩子和 CJS 运行时版本。如果您需要保留 CJS 输出格式,请考虑使用打包器在构建后步骤中将 Svelte 的 ESM 输出转换为 CJS。(#8613)
Svelte 函数的类型更严格永久链接
现在 createEventDispatcher
、Action
、ActionReturn
和 onMount
的类型更严格了
createEventDispatcher
现在支持指定有效负载是可选的、必需的还是不存在的,并且会相应地检查调用点(#7224)
ts
import {createEventDispatcher } from 'svelte';constdispatch =createEventDispatcher <{optional : number | null;required : string;noArgument : null;}>();Expected 2-3 arguments, but got 1.2554Expected 2-3 arguments, but got 1.Argument of type '"surprise"' is not assignable to parameter of type 'null | undefined'.2345Argument of type '"surprise"' is not assignable to parameter of type 'null | undefined'.// Svelte version 3:dispatch ('optional');dispatch ('required'); // I can still omit the detail argumentExpected 2-3 arguments, but got 1.2554Expected 2-3 arguments, but got 1.dispatch ('noArgument', 'surprise'); // I can still add a detail argumentArgument of type '"surprise"' is not assignable to parameter of type 'null | undefined'.2345Argument of type '"surprise"' is not assignable to parameter of type 'null | undefined'.// Svelte version 4 using TypeScript strict mode:dispatch ('optional');dispatch ('required'); // error, missing argumentdispatch ('noArgument', 'surprise'); // error, cannot pass an argument
Action
和ActionReturn
现在具有默认参数类型undefined
,这意味着如果您想指定此操作接收参数,则需要键入泛型。迁移脚本将自动迁移此项(#7442)
const action: Action = (node, params) => { .. } // this is now an error if you use params in any way
const action: Action<HTMLElement, string> = (node, params) => { .. } // params is of type string
- 如果您异步地从
onMount
返回一个函数,现在将显示一个类型错误,因为这可能是您代码中的一个错误,您希望在销毁时调用回调,而它只会对同步返回的函数执行此操作(#8136)
// Example where this change reveals an actual bug
onMount(
// someCleanup() not called because function handed to onMount is async
async () => {
const something = await foo();
// someCleanup() is called because function handed to onMount is sync
() => {
foo().then(something => ..
// ..
return () => someCleanup();
}
);
使用 Svelte 的自定义元素永久链接
使用 Svelte 创建自定义元素已经过全面检修并得到显著改进。tag
选项已弃用,取而代之的是新的 customElement
选项
<svelte:options tag="my-component" />
<svelte:options customElement="my-component" />
进行此更改是为了允许 更多可配置性 以适应高级用例。迁移脚本将自动调整您的代码。属性的更新时机也略有改变。(#8457)
SvelteComponentTyped 已弃用永久链接
SvelteComponentTyped
已弃用,因为 SvelteComponent
现在具有其所有类型化功能。用 SvelteComponent
替换 SvelteComponentTyped
的所有实例。
import { SvelteComponentTyped } from 'svelte';
import { SvelteComponent } from 'svelte';
export class Foo extends SvelteComponentTyped<{ aProp: string }> {}
export class Foo extends SvelteComponent<{ aProp: string }> {}
如果您之前已将 SvelteComponent
用作组件实例类型,现在您可能会看到一个有点不透明的类型错误,可以通过将 : typeof SvelteComponent
更改为 : typeof SvelteComponent<any>
来解决此问题。
<script>
import ComponentA from './ComponentA.svelte';
import ComponentB from './ComponentB.svelte';
import { SvelteComponent } from 'svelte';
let component: typeof SvelteComponent;
let component: typeof SvelteComponent<any>;
function choseRandomly() {
component = Math.random() > 0.5 ? ComponentA : ComponentB;
}
</script>
<button on:click={choseRandomly}>random</button>
<svelte:element this={component} />
迁移脚本会自动为您执行这两项操作。(#8512)
过渡默认是局部的永久链接
过渡现在默认是局部的,以避免页面导航时的混乱。“局部”意味着如果过渡在嵌套控制流块(each/if/await/key
)内,而不是直接父块,而是上面创建/销毁的块,则不会播放。在以下示例中,slide
入场动画仅在 success
从 false
变为 true
时播放,但当 show
从 false
变为 true
时不会播放
{#if show}
...
{#if success}
<p in:slide>Success</p>
{/each}
{/if}
要使过渡成为全局,请添加 |global
修饰符 - 然后当上面任何控制流块被创建/销毁时,它们将播放。迁移脚本会自动为您执行此操作。(#6686)
默认插槽绑定永久链接
默认插槽绑定不再公开给命名插槽,反之亦然
<script>
import Nested from './Nested.svelte';
</script>
<Nested let:count>
<p>
count in default slot - is available: {count}
</p>
<p slot="bar">
count in bar slot - is not available: {count}
</p>
</Nested>
这使得插槽绑定更加一致,因为当例如默认插槽来自列表而命名插槽不是时,行为是未定义的。(#6049)
预处理器永久链接
应用预处理器的顺序已更改。现在,预处理器按顺序执行,并且在一个组中,顺序是标记、脚本、样式。
ts
import {preprocess } from 'svelte/compiler';const {code } = awaitpreprocess (source ,[{markup : () => {console .log ('markup-1');},script : () => {console .log ('script-1');},style : () => {console .log ('style-1');}},{markup : () => {console .log ('markup-2');},script : () => {console .log ('script-2');},style : () => {console .log ('style-2');}}],{filename : 'App.svelte'});// Svelte 3 logs:// markup-1// markup-2// script-1// script-2// style-1// style-2// Svelte 4 logs:// markup-1// script-1// style-1// markup-2// script-2// style-2
例如,如果您正在使用 MDsveX
,这可能会影响您 - 在这种情况下,您应该确保它在任何脚本或样式预处理器之前。
preprocess: [
vitePreprocess(),
mdsvex(mdsvexConfig)
mdsvex(mdsvexConfig),
vitePreprocess()
]
每个预处理器还必须有一个名称。(#8618)
新的 eslint 包永久链接
eslint-plugin-svelte3
已弃用。它可能仍然适用于 Svelte 4,但我们对此不作任何保证。我们建议切换到我们的新包 eslint-plugin-svelte。请参阅 此 Github 帖子,了解如何迁移的说明。或者,您可以使用 npm create svelte@latest
创建一个新项目,选择 eslint(可能还有 TypeScript)选项,然后将相关文件复制到您现有的项目中。
其他重大更改永久链接
inert
属性现在应用于输出元素,以使其对辅助技术不可见并防止交互。(#8628)- 运行时现在使用
classList.toggle(name, boolean)
,这可能无法在非常旧的浏览器中使用。如果您需要支持这些浏览器,请考虑使用 polyfill。(#8629) - 运行时现在使用
CustomEvent
构造函数,这可能无法在非常旧的浏览器中使用。如果您需要支持这些浏览器,请考虑使用 polyfill。(#8775) - 使用
StartStopNotifier
接口(传递给writable
等的创建函数)从头开始实现自己的存储的人员现在需要传递更新函数以及设置函数。这对使用存储或使用现有 Svelte 存储创建存储的人员没有任何影响。(#6750) derived
现在会对传递给它的假值引发错误,而不是存储。(#7947)svelte/internal
的类型定义已被删除,以进一步阻止使用那些不是公共 API 的内部方法。其中大部分可能会在 Svelte 5 中更改- 现在对 DOM 节点进行批量删除,这会稍微改变其顺序,可能会影响在这些元素上使用
MutationObserver
时触发的事件顺序(#8763) - 如果您之前通过
svelte.JSX
命名空间增强了全局类型,则需要迁移到使用svelteHTML
命名空间。类似地,如果您使用svelte.JSX
命名空间来使用其中的类型定义,则需要迁移到使用svelte/elements
中的类型。您可以在 此处 找到有关如何操作的更多信息