本迁移指南概述了如何从 Svelte 版本 3 迁移到 4。 有关每项更改的更多详细信息,请参阅链接的 PR。 使用迁移脚本自动迁移其中一些: npx svelte-migrate@latest svelte-4
英This migration guide provides an overview of how to migrate from Svelte version 3 to 4. See the linked PRs for more details about each change. Use the migration script to migrate some of these automatically: npx svelte-migrate@latest svelte-4
如果你是库作者,请考虑是否仅支持 Svelte 4 或者是否也可以支持 Svelte 3。 由于大多数重大更改不会影响很多人,因此这很容易实现。 另请记住更新 peerDependencies
中的版本范围。
英If you're a library author, consider whether to only support Svelte 4 or if it's possible to support Svelte 3 too. Since most of the breaking changes don't affect many people, this may be easily possible. Also remember to update the version range in your peerDependencies
.
最低版本要求(Minimum version requirements)permalink
- 升级到节点 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 conditions for bundlers)permalink
现在,打包程序在为浏览器构建前端打包包时必须指定 browser
条件。 SvelteKit 和 Vite 会自动为你处理这个问题。 如果你使用其他任何方法,你可能会观察到生命周期回调(例如 onMount
)未被调用,并且你需要更新模块解析配置。
英Bundlers must now specify the browser
condition when building a frontend bundle for the browser. SvelteKit and Vite will handle this automatically for you. If you're using any others, you may observe lifecycle callbacks such as onMount
not get called and you'll need to update the module resolution configuration.
- 对于 Rollup,这是通过在
@rollup/plugin-node-resolve
插件的选项中设置browser: true
来完成的。 有关更多详细信息,请参阅rollup-plugin-svelte
文档 - 对于 wepback,这是通过将
"browser"
添加到conditionNames
数组来完成的。 如果你已设置,你可能还需要更新alias
配置。 有关更多详细信息,请参阅svelte-loader
文档
(#8516)
英(#8516)
删除 CJS 相关输出(Removal of CJS related output)permalink
Svelte 不再支持 CommonJS (CJS) 编译器输出格式,并且还删除了 svelte/register
钩子和 CJS 运行时版本。 如果你需要保留 CJS 输出格式,请考虑使用打包器在构建后步骤中将 Svelte 的 ESM 输出转换为 CJS。 (#8613)
英Svelte no longer supports the CommonJS (CJS) format for compiler output and has also removed the svelte/register
hook and the CJS runtime version. If you need to stay on the CJS output format, consider using a bundler to convert Svelte's ESM output to CJS in a post-build step. (#8613)
Svelte 函数的更严格类型(Stricter types for Svelte functions)permalink
现在 createEventDispatcher
、Action
、ActionReturn
和 onMount
有更严格的类型:
英There are now stricter types for createEventDispatcher
, Action
, ActionReturn
, and 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 自定义元素(Custom Elements with Svelte)permalink
使用 Svelte 创建自定义元素已经过彻底修改并显着改进。 tag
选项已弃用,取而代之的是新的 customElement
选项:
英The creation of custom elements with Svelte has been overhauled and significantly improved. The tag
option is deprecated in favor of the new customElement
option:
<svelte:options tag="my-component" />
<svelte:options customElement="my-component" />
进行此更改是为了允许 更多可配置性 用于高级用例。 迁移脚本将自动调整你的代码。 属性的更新时间也略有变化。 (#8457)
英This change was made to allow more configurability for advanced use cases. The migration script will adjust your code automatically. The update timing of properties has changed slightly as well. (#8457)
SvelteComponentTyped 已弃用(SvelteComponentTyped is deprecated)permalink
SvelteComponentTyped
已弃用,因为 SvelteComponent
现在具有其所有类型功能。 将 SvelteComponentTyped
的所有实例替换为 SvelteComponent
。
英SvelteComponentTyped
is deprecated, as SvelteComponent
now has all its typing capabilities. Replace all instances of SvelteComponentTyped
with SvelteComponent
.
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>
可以解决此问题。
英If you have used SvelteComponent
as the component instance type previously, you may see a somewhat opaque type error now, which is solved by changing : typeof SvelteComponent
to : 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)
英The migration script will do both automatically for you. (#8512)
默认情况下,转场是本地的(Transitions are local by default)permalink
现在默认情况下,转场是本地的,以防止页面导航发生混乱。 "local" 意味着如果转换位于嵌套控制流块 (each/if/await/key
) 内且不是直接父块但创建/销毁了其上方的块,则该转换将不会播放。 在以下示例中,slide
介绍动画仅在 success
从 false
到 true
时播放,但在 show
从 false
到 true
时不会播放:
英Transitions are now local by default to prevent confusion around page navigations. "local" means that a transition will not play if it's within a nested control flow block (each/if/await/key
) and not the direct parent block but a block above it is created/destroyed. In the following example, the slide
intro animation will only play when success
goes from false
to true
, but it will not play when show
goes from false
to true
:
{#if show}
...
{#if success}
<p in:slide>Success</p>
{/each}
{/if}
要使转换全局化,请添加 |global
修饰符 - 然后它们将在创建/销毁上面的任何控制流块时播放。 迁移脚本将自动为你执行此操作。 (#6686)
英To make transitions global, add the |global
modifier - then they will play when any control flow block above is created/destroyed. The migration script will do this automatically for you. (#6686)
默认插槽绑定(Default slot bindings)permalink
默认槽绑定不再暴露给命名槽,反之亦然:
英Default slot bindings are no longer exposed to named slots and vice versa:
<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)
英This makes slot bindings more consistent as the behavior is undefined when for example the default slot is from a list and the named slot is not. (#6049)
预处理器(Preprocessors)permalink
应用预处理器的顺序已更改。 现在,预处理器按顺序执行,在一组内,顺序是标记、脚本、样式。
英The order in which preprocessors are applied has changed. Now, preprocessors are executed in order, and within one group, the order is markup, script, style.
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
,这可能会影响你 - 在这种情况下,你应该确保它出现在任何脚本或样式预处理器之前。
英This could affect you for example if you are using MDsveX
- in which case you should make sure it comes before any script or style preprocessor.
preprocess: [
vitePreprocess(),
mdsvex(mdsvexConfig)
mdsvex(mdsvexConfig),
vitePreprocess()
]
每个预处理器还必须有一个名称。 (#8618)
英Each preprocessor must also have a name. (#8618)
新的 eslint 包(New eslint package)permalink
eslint-plugin-svelte3
已弃用。 它可能仍然适用于 Svelte 4,但我们对此不做任何保证。 我们建议切换到我们的新软件包 eslint-plugin-svelte。 有关如何迁移的说明,请参阅 这个 Github 帖子。 或者,你可以使用 npm create svelte@latest
创建一个新项目,选择 eslint(可能还有 TypeScript)选项,然后将相关文件复制到现有项目中。
英eslint-plugin-svelte3
is deprecated. It may still work with Svelte 4 but we make no guarantees about that. We recommend switching to our new package eslint-plugin-svelte. See this Github post for an instruction how to migrate. Alternatively, you can create a new project using npm create svelte@latest
, select the eslint (and possibly TypeScript) option and then copy over the related files into your existing project.
其他重大变更(Other breaking changes)permalink
inert
属性现在应用于外部元素,使它们对辅助技术不可见并阻止交互。 (#8628)- 运行时现在使用
classList.toggle(name, boolean)
,这可能无法在非常旧的浏览器中运行。 如果你需要支持这些浏览器,请考虑使用 polyfill。 (#8629) - 运行时现在使用
CustomEvent
构造函数,该构造函数可能无法在非常旧的浏览器中工作。 如果你需要支持这些浏览器,请考虑使用 polyfill。 (#8775) - 人们使用
svelte/store
中的StartStopNotifier
接口(传递给writable
等的创建函数)从头开始实现自己的存储,现在除了设置函数之外还需要传递更新函数。 这对使用存储或使用现有 Svelte 存储创建存储的人没有影响。 (#6750) derived
现在将在错误值上抛出错误,而不是传递给它的存储。 (#7947)- 删除了
svelte/internal
的类型定义,以进一步阻止使用那些非公共 API 的内部方法。 其中大部分可能会在 Svelte 5 中发生变化 - 现在批量删除 DOM 节点,这会稍微改变其顺序,如果你在这些元素上使用
MutationObserver
(#8763),这可能会影响触发事件的顺序 - 如果你之前通过
svelte.JSX
命名空间增强了全局类型,则需要将其迁移到使用svelteHTML
命名空间。 同样,如果你使用svelte.JSX
命名空间来使用其中的类型定义,则需要迁移这些命名空间以使用svelte/elements
中的类型。 你可以找到有关如何执行 here 的更多信息