Vue 3 不是最佳选择? 耗时两周从 Vue 2 迁移到 Svelte 后:代码执行更快、体验更佳

  • 2022-12-09
    北京
  • 本文字数:4158 字

    阅读完需:约 14 分钟

架构选型问题是每位 Web 开发人员都绕不开的一道难关。

 

架构是整个 IT 系统的根基,一个错误的选型,可能造成巨大的财务、人力损失。现在随着各种新应用的崛起,到底是选择 Bootstrap、Angular、React、Vue 还是 Svelte,让开发人员很犯难。而且随着 Vue 3 发布、Vue 2 即将停止维护,不少企业开始考虑升级问题,其中不止一家企业选择从 Vue 迁移到了 Svelte,并对 Svelte 的性能表示满意。

 

Sophie 是一名 UI/UX 设计师/前端开发者,她介绍了在知晓 Vue 2 即将停止维护后,其团队在选择新架构过程中的纠结、做出最终选择的原因、迁移的全过程以及迁移后的效果和收益。

 

为什么要迁移?

 

Sophie 表示,之所以要进行迁移,一方面是知晓了 Vue 2 即将停止维护,另一方面也是想改善开发者的工作体验,特别是类型检查、性能和构建时间这几项核心指标。之所以没有考虑 React,是因为它的学习过程太耗时间,而且也不提供能开箱即用的解决方案。Vue 和 Svelte 在这方面的优势明显更大。另外,Vue 和 Svelte 的单文件组件还通用相同的概念:逻辑均由 JS 表达、结构依托 HTML,样式则由 CSS 定义。

 

在开展了一系列相关研究后,Sophie 的团队最终选择了 Svelte。

 

关于 Vue 3 和 Svelte 哪个更好的争论一直是前端圈的热门话题,Vue 作者尤雨溪去年也在 GitHub 上创建了一个仓库用来对比 Svelte 和 Vue 3 组件。

 

为了公平起见,尤雨溪选择了 todomvc 来进行构建比较,然后列举了一系列的步骤方案。 最终结论是:

 

  • Svelte 单组件在普通模式下比 Vue 3 单组件约大 70%(这个 70%指的是当前 todomvc 组件的大小对比,并不代表着所有 Svelte 组件 都比 Vue 3 组件大 70%),在 SSR 模式下大 110%;

  • 在理论上,如果一个应用程序包含超过 15.04 / 0.78 约等于 19 个 todomvc 大小的组件,则 Svelte 应用程序将最终比 Vue 应用程序体积更大。在 SSR 场景中,这个阈值会更低。对于某个项目来说,当编写的组件大于 19 个(SSR 模式为 13 个组件),Svelte 的优势与 Vue 3 相比就不存在了。

仓库地址:https://github.com/yyx990803/vue-svelte-size-analysis

 

为什么选择 Svelte?

 

与 Vue 3 相比,Svelte 优势明显

 

在 Sophie 的项目中,其团队认为 Svelte 与 Vue 3 相比主要有以下几点优势:

 

第一,Svelte 的留存率更高。下图为不同框架在过去五年内的留存率展示,留存率公式为:会再次使用/(会再次使用+不会再次使用)。这部分开发者数据来自 JS 现状调查,可以看到 Svelte 在留存率方面位列第二,而 Vue 则居第四。

 

2021 年前端开发框架留存率榜单,Svelte 位列第二、Vue 3 排名第四。

 

由此看来,用过 Svelte 的开发者们普遍愿意再次使用。

 

第二,Svelte 的类型机制更完善。

Svelte 拥有更简单的组件设计流程和内置的类型化事件,由此实现的更佳类型体验更贴合人性化需求。

 

第三,限制全局访问。在使用 Svelte 时,可以从其他文件处导入 enums 并在模板中使用;而 Vue 3 则做不到这一点。

 

前端堆栈 Escape Benchmark 汇总

 

第四,语法更简明。Sophie 表示,她个人认为 Svelte 的语法要比 Vue 更优雅、也更易用一点。同时大家可以参考以下代码,体会二者之间的不同。

 

Svelte:

<script>    let firstName = "";    let town = "";    $: fullName = "Full name: " + firstName + ' ' + lastName;    const reset = () => {        firstName = "";        lastName = "";    }</script><main>    <div>        <label>First name</label>        <input type="text" bind:value={firstName}>        <label>Last name</label>        <input type="text" bind:value={lastName}>        <button on:click={reset}>Reset</button>    </div>    <div>        {fullName}    </div></main><style>  main{    background-color: white;  }</style>
复制代码

Vue:

<template>  <main>    <label>First name </label>    <input type="text" v-model="firstName"/>    <label>Last name </label>    <input type="text" v-model="lastName"/>    <div>        Full name: {{fullName}}     </div>    <button @click="handleReset">Reset</button>  </main></template><script setup>import { ref, computed } from 'vue'const firstName = ref('')const lastName = ref('') const fullName = computed(() => { return firstName.value + " " + lastName.value; }) function handleReset() {    firstName.value = ""    lastName.value = ""}</script><style scoped>main{  background-color: white;}</style>
复制代码

 

第五,无需额外的 HTML div