发布时间

On Escape 的 Vue 2 到 Svelte 迁移

作者

最近,Escape 的团队分享了一篇 博客文章,讨论了他们从 Vue 2 迁移到 Svelte 的过程,并比较了 Vue 3 和 Svelte。我们发现文章中包含一些不准确的信息。在这篇文章中,我们将从我们的角度分享一些想法,并希望澄清文章可能带来的潜在误解。


在我们深入细节之前,我们想强调我们尊重开发者对技术的选择,并相信你应该使用最能提高你生产力的工具。我们也对 Svelte 团队抱有极大的敬意,特别是他们对 API 设计中追求简洁和精炼的努力。

澄清要点

原始文章包含一个比较图表,其中包含一些需要澄清的问题。

comparison-chart

类型

Vue 3 不支持类型化事件

从 3.2 版本开始就支持了(相关文档)。

除此之外,我们不同意“Svelte 提供了更好的类型体验”的结论。据我们所知,Vue 3 和 Svelte 在当前状态下的 TypeScript 支持相当。

受限的全局访问

无法在 Vue 组件中导入和使用 TypeScript 枚举

这是错误的。这里有一个 示例。实际上,Vue 和 Svelte 的工作方式完全相同。

外部响应式对象

部分(仅限对象)

这有点含糊,在文章中没有进一步解释,但 Vue 的所有 响应式 API,包括 refcomputed 和观察者,都可以在组件之外使用,作为简单的跨组件存储。

错误边界

Vue 一直提供捕获从子组件树中抛出的错误的能力,通过 onErrorCaptured 生命周期钩子,在祖先组件中捕获。这包括从异步事件处理程序和生命周期钩子中抛出的错误。

Vue 没有内置的机制直接在模板中处理 Promise 状态,但可以使用像 vue-promised 这样的库轻松实现。

与库集成

在 Svelte 中添加纯 JS 插件更简单

文章中包含一个与 Prism.js 集成的示例来支持这一点。然而,在 Vue 中使用 <script setup> 时,它将以完全相同的方式工作。

元框架

文章还比较了基于 Vue 和 Svelte 的元框架,即 Nuxt 和 SvelteKit,并将 Vite 列为 SvelteKit 的优势。然而,Nuxt 3 刚刚发布稳定版本,并且默认情况下也使用 Vite。Nuxt 团队和 SvelteKit 团队都与 Vite 团队有着密切的合作关系。

语法

我们尊重不同的语法偏好,但讨论设计之间的权衡也很重要。

首先,我们不认为单引号或双引号、元素绑定指令或小胡子风格的控制流,或者需要额外的 <template> 标签等差异会对你的长期生产力产生实质性的影响。模板语法是随着时间的推移会很快内化的东西。

在响应式方面,Svelte 确实提供了一种非常简洁的语法来声明和修改组件状态,并且有一些值得讨论的要点。

  1. 对于表达响应式,有三个基本概念:状态、派生状态和效果。Svelte 使用普通变量表示状态,使用神奇的 $ 符号表示派生状态和效果。Vue 使用显式 API 来声明每个概念(refcomputedwatchEffect)。一些用户可能更喜欢神奇的语法,而另一些用户可能更喜欢显式 API - 两者都有其存在的空间。

  2. Svelte 的基于编译器的响应式限制了这种语法可以使用的范围。它不能在 Svelte 组件之外使用,也不能在没有构建步骤的情况下使用。而对于 Vue 来说,Composition API 可以以相同的方式在组件内部和外部使用,甚至在没有构建步骤的情况下使用。

  3. 由于(2),Svelte 需要提供一组额外的 API(存储)来管理组件之外的相同响应式概念。由于两种语法不容易相互转换,因此在将逻辑从组件中移出或重构时会产生摩擦。

话虽如此,我们一直在 Vue 中尝试一项名为 响应式转换 的功能,它允许你像这样编写 Vue 组件

vue
<script setup>
let count = $ref(0)

function increment() {
  count++
}
</script>

<template>
  <button @click="increment">{{ count }}</button>
</template>

它提供了与 Svelte 相似的简洁程度,但也可以在纯 JS/TS 文件中使用。它也很容易将语法自动反糖化成纯 Composition API 代码。

性能和包大小

改进的性能和包大小被认为是迁移的原因之一。虽然毫无疑问 Svelte 具有高性能和轻量级,但与其他框架相比的改进并不一定有保证。实际上,它可能取决于其他因素,包括实际实现、优化空间和应用程序的规模。

作为参考,Vue 3 在 js-framework-benchmark 中通过少量优化就可以超越 Svelte。Vue 3 通过一种称为 编译器感知的虚拟 DOM 的运行时/编译器混合渲染模型实现了这一点。它利用在编译时可以知道的信息来优化运行时性能,同时保持与手动编写的渲染函数的兼容性。

在包大小方面,Svelte 非常适合生成仅包含一个或几个组件的小部件或 Web 组件,但其轻量级的运行时大小可能会被其与其他框架相比更详细的每个组件代码输出所抵消。 这项研究 表明,Svelte 的应用程序包大小在大型应用程序中可能成为劣势,尤其是在启用 SSR 渲染的情况下。

需要注意的是,Svelte 和 Vue 3 都很可能足够满足你的使用场景,并且这两个框架都将继续发展和改进。Svelte 团队已经提到了在 Svelte 4 中改进每个组件代码输出大小的计划。在 Vue 方面,我们也在探索一种替代的、更高性能的编译策略(代号:Vapor),它受到 Solid.js 的启发。Vapor 模式将允许 Vue 组件被编译成一种不涉及虚拟 DOM 运行时的格式。它目前仍处于研究阶段,我们将在 2023 年分享更多关于它的信息。

State of JS 调查中的保留数据

此外,另一个需要考虑的重要因素是来自 State of JavaScript 调查的满意度评分。虽然 Svelte 在调查中绝对值得其高评分,但使用这种评分来决定是否应该迁移您的应用程序可能会对您的团队产生负面影响,因为其中存在很多缺失的背景信息。

在调查中,框架的满意度评分被定义为再次使用该框架的用户数量与不使用该框架的用户数量的比率。请注意,此数字仅基于使用过某个框架的用户反馈计算得出。公平地说,这种公式自然有利于更新的技术。理论上,如果一个框架只有一个用户,并且该用户报告说他们会再次使用它,那么该框架将获得完美的 100% 评分!

处于早期阶段的技术主要吸引那些喜欢该技术本身的用户。然而,当它成为主流时,它开始被更大规模的组织采用,这些组织的科技选择决策是由上而下做出的。这意味着将会有越来越多的用户不得不使用它,无论他们个人喜好如何。它还吸引了更多路过用户,他们纯粹出于其流行度而尝试它,但可能不是目标受众。此外,更广泛的采用在更广泛的场景中挑战了该技术,暴露了可能只在更苛刻的情况下才会出现的问题。

另一方面,一项较新的技术如果未能在其早期采用者中获得比现有技术更高的分数,可能甚至不会进入调查。

这绝不意味着贬低 Svelte 的成就,也不是我们的借口。Vue 2 到 Vue 3 的过渡并不像预期的那样顺利,并且确实影响了满意度评分。我们希望通过继续改进 Vue 3 来扭转局面。但希望您能明白:这个数字本身并不能完全代表一个框架的“好坏”,更不用说它是否适合您的用例了。请记住,调查通常会受到许多混杂变量和背景的影响,这些变量和背景可能不适用于您的情况,因此请谨慎对待将它们视为金科玉律。

结论

归根结底,我们认为 Svelte 是一个很棒的框架,我们祝 Escape 在使用 Svelte 的工作中一切顺利!毕竟,虽然我们想澄清一些比较点,但我们都是同一个社区的一部分,希望帮助人们为用户构建出色的产品。


最后,如果您有一个基于 Vue 2 的代码库,并且担心即将到来的生命周期结束(2023 年底),迁移并不一定是唯一的选择。Vue 2 是一项稳定、成熟且经过实战检验的技术,它将继续发挥作用。在进行重大迁移之前,请务必评估您真正的收益和成本。对于需要处理安全合规性的团队,我们正在与 HeroDevs 合作,为 Vue 2 提供付费的扩展支持。如果您的团队需要此服务,请在此处注册您的兴趣 here.