主打一个“小巧灵动”:Vite + Svelte

开发
在研发小型项目时,传统的 Vue、React 显得太“笨重”。本文主要针对开发小型项目的场景,谈谈 Vite+Svelte 是如何让项目变得“小巧灵动”,并横向对比 Svelte 和 Vue 的性能表现,对二者的加载流程做详细分析。

一、背景

为了统一技术标准、提升协作效率,通常在前端团队内部只会保留一套通用的研发框架。尤其是在团队初创时期,团队成员会考虑易用性、社区活跃程度、学习成本等因素,选择一个合适的研发框架并一直推行和使用下去。

国内的前端团队比较青睐 Vue和 React,我们团队内部的主要研发框架也是 Vue,包括组件库、工具库、脚手架等等,都是围绕 Vue 展开来做研发。

坚持使用一个技术栈虽然让团队协作变得高效,也不用重复“造轮子”,同时提升了人员“流通性”,有它不可忽略的优势。但没有任何一款框架是“银弹”,例如 Vue,它的通用性很好,但在某些特殊场景下,我们会有更好的选择。

例如,当我们在开发一些小型项目时,会发现至少有两个明显的问题:

  • 框架太“重”了:通常一个小型项目只由少数几个简单页面构成,如果使用 Vue 或者 React 这些框架来研发的话,有点“大材小用”了。构建的产物中包含了不少框架运行时代码(虚拟 DOM、响应式、状态管理等),这些代码对于小型项目而言是冗余的,它们影响了包体大小,进而影响页面的启动速度和执行性能。
  • 打包太慢了:以 Vue CLI 为例,它的底层基于 Webpack,虽然 Webpack 具备更强大的功能和灵活性,但相比于 Vite、Esbuild 这些以速度为标杆的构建工具来说,它的速度确实慢了一些,影响了研发效率。

面对这两个问题,我们似乎有更好的技术方案可选:使用更轻量的 Vite + Svelte。本文就是针对开发小型项目的场景,谈谈 Vite+Svelte 是如何让项目变得“小巧灵动”。

注意:本篇所有针对 Svelte 的性能观点,都是基于小型项目这个前提下提出。事实上,随着项目规模的增长, Svelte 的性能、包体大小优势会逐渐减小,甚至不如 Vue 或 React。

理论上在普通 CSR 项目中,组件数量超过19个时, Svelte 就失去了它的包体大小优势。

二、Vite 和 Svelte 简介

先了解下 Vite 和 Svelte。

2.1 Vite

Vite 是尤雨溪尤大写的一款高效的前端构建工具,相比于 Webpack,它最大的优势就是“”。

在开发环境下,Vite 使用高性能的 Esbuild 来进行预构建,并利用现代浏览器对 ESM 的支持,直接将预构建好的ES模块丢给浏览器进行解析执行,无需在每次变更代码时都重新编译代码,具有更快的冷启动速度和热更新效率。

在生产环境下,Vite 基于 Rollup 进行打包,Rollup 同样支持 ESM 语法,并且具有更快速高效的 Treeshaking,一般情况下,Rollup 具有更小的包体大小和更快的构建速度。

参考 Github 上的构建工具横向对比 benchmark

图片

(图片来源:https://github.com)

可以看到无论是冷启动、热更新还是生产环境打包,Vite 都是优于 Webpack 的。尤其是在开发过程中的热更新很快,大大优化了开发体验。

2.2 Svelte

Svelte 是由 Rollup 的作者 Rich Harris(前端轮子哥) 写的一款前端框架。在语法上,Svelte 和 Vue 类似。它和传统框架(如 Vue、React)的最大差异就在于:在构建阶段,Svelte 就将代码编译为“纯粹”的 JavaScript 代码,几乎没有运行时。

这意味着在小型项目中,它打出来的包更小,在运行时,它也不需要复杂的状态管理和虚拟 DOM,在性能上的表现也更好。

在前端大佬 Jacek Schae 的前端框架横向测评中(测评简述:使用各个前端框架来编写同一个标准 App - RealWorld,并横向对比它们的表现),可以看到,Svelte 无论是在首屏渲染速度、包体大小还是代码行数上都展现了较大的优势,全部跻身前三。

首屏渲染速度

图片

(图片来源:https://medium.com)

包体大小:

图片

(图片来源:https://medium.com)

代码行数:


图片

(图片来源:https://medium.com)

三、搭建 Vite+Svelte 项目

在基本了解了 Vite 和 Svelte 之后,来看看如何着手去搭建一个 Vite+Svelte 的项目。

3.1 全局安装 Vite

通过 npm 全局安装 Vite:

npm install vite -g

3.2 创建 Svelte 项目

Vite 原生支持直接通过脚手架创建 Svelte 项目,执行以下命令:

npm create vite@latest

命令行中会出现引导,按照提示输入项目的名称并直接选择 Svelte 框架即可。

✔ Project name: vite-svelte-demo


? Select a framework: › - Use arrow-keys. Return to submit.
    Vanilla
    Vue
    React
    Preact
    Lit
❯   Svelte
    Solid
    Qwik
    Others


? Select a variant: › - Use arrow-keys. Return to submit.
    TypeScript
❯   JavaScript
    SvelteKit ↗

3.3 运行项目

通过以下命令运行项目:

cd vite-svelte-demo
npm install
npm run dev

图片

这样一来,整个 Vite + Svelte 的项目结构就搭建好了,开箱即用。整个项目的目录结构如下:

|-node_modules        -- 项目依赖
|-public              -- 公共文件
  |--vite.svg        
|-src                 -- 源文件
  |-assets           
  |-lib               
  |--App.svelte       -- 项目根组件
  |--app.css          -- 项目根样式
  |--main.js          -- 项目入口文件
|--.gitignore         
|-- index.html        -- 首页index.html
|-- package-lock.json 
|-- package.json      
|-- tsconfig.json 
|-- svelte.config.js  -- svelte配置文件
|-- vite.config.js    -- vite配置文件

可以看到,整个项目结构基本和 Vue 类似,只是组件的后缀名改为了.svelte,新增了 vite.config.js 和  svelte.config.js 两个配置文件。

3.4 配置

Vite+Svelte 支持开箱即用,项目的初始配置也很简单,没有任何额外配置。

vite.config.js:用于配置 Vite 构建工具的行为,例如入口文件、输出目录、插件、devServer 等。

// vite.config.js
import { defineConfig } from 'vite'
import { svelte } from '@sveltejs/vite-plugin-svelte'


export default defineConfig({
  plugins: [svelte()],
})

svelte.config.js:用于配置 Svelte 项目的各种选项,例如别名、预处理器、插件等。

// svelte.config.js
import { vitePreprocess } from '@sveltejs/vite-plugin-svelte'


export default {
  preprocess: vitePreprocess(),
}

在工程配置这里,唯一需要注意的是,Vite 默认情况打出的包体仅支持现代浏览器(支持 ESM ),如果要兼容低版本浏览器,可以使用官方提供的 @vitejs/plugin-legacy插件:

// vite.config.js
import { defineConfig } from "vite";
import { svelte } from "@sveltejs/vite-plugin-svelte";
import legacy from "@vitejs/plugin-legacy";


export default defineConfig({
  plugins: [
    svelte(),
    legacy({
      // 设置需要兼容的目标浏览器版本
      targets: [
        "Android >= 4.4",
        "iOS >= 9",
        "ie >= 11",
        "not Android < 4.4",
        "not iOS < 9",
        "not ie < 11",
      ],
      additionalLegacyPolyfills: ["regenerator-runtime/runtime"],
      renderLegacyChunks: true,
    }),
});

更多配置项可参考官网的 Vite 配置文档和 Svelte 配置文档。

四、开发体验优化

项目搭建完成后,后续就是根据业务需求来开发 Svelte 组件和完善业务逻辑。整个开发过程中,体验感还是不错的。

详细的开发流程不再赘述,想要了解更多关于 Vite 和 Svelte 内容,可以参考 Vite 官方文档和 Svelte 官方文档。这里我们主要来看看 Vite 和 Svelte 分别在开发体验上带来的一些优化。

4.1 Vite 的开发体验太棒了

首先,Vite 的开发体验太棒了。它的构建速度极快,对开发效率有很明显的提升。

在开发环境下,Webpack 每次都需要对改动的部分进行重新编译打包,耗时几秒钟,而 Vite 则不需要重新打包,只需要把更新后的 ESM 代码交付给浏览器就ok,几乎是即时更新。

同时在构建生产环境包时,也明显比原先的 Vue 项目要快了近50%。别小看这一点速度的提升,让整个开发体验好了不少。

4.2 Svelte 的语法更优雅?

如果你跟随上面步骤搭建了项目,那你可以打开项目中的 Counter.svelte 文件看看,会发现 Svelte 组件的基本结构和 Vue 几乎一致,也是由 script、template 和 style 三部分组成,唯一的差异在于 Svelte 中不需要像 Vue 一样额外使用来作为 DOM 结构的根标签。

<script>
  let count = 0
  const increment = () => {
    count += 1
  }
</script>


<button on:click={increment}>
  count is {count}
</button>


<style>
  ...
</style>

在语法上,Svelte 和 Vue 也非常相似,但个人更喜欢 Svelte 的一些简洁的语法设计,举一些例子:

插值表达式:Svelte 的插值表达式只需要单个{},而 Vue 则需要两层{{}},并且 Svelte 还有一些简写语法,例如 src={src} 可以简写为 {src}。

// Svelte的插值表达式
<div {src}>
  count is {count}
</<div>


// Vue的插值表达式
<template>
  <div :src="src">
    count is {{ count }}
  </div>
</template>

响应式:Svelte 声明的变量直接支持响应式,而在 Vue 中则需要使用 ref 来声明。

// Svelte
let message = 'Svelte';


// Vue
import { ref } from 'vue';
const message = ref('Vue');

computed 计算属性 / watch 监听:Svelte 的$: 代码块类似于 Vue 的 computed 计算属性和 watch 状态监听的结合体。

// Svelte的计算属性
$: info = name + age


// Svelte的监听
let val
$: {
  console.log(`你输入的内容是: ${val}`);
}


// Vue的计算属性
import { computed } from 'vue';
const info = computed(() => {
  return name + age
});


// Vue的监听
import { watch } from 'vue';


let val = ref(''); 
watch(val, (newValue, oldValue) => { 
  console.log(`你输入的内容是: ${val}`);
});

虽然差异没有很大,但这些简洁的语法,至少让我个人感觉写项目时更流畅,体验感很不错。

这些就是 Vite 和 Svelte 带来的开发体验上的一些优化。

五、Svelte 和 Vue 性能对比

上面我们了解了如何搭建 Vite+Svelte 项目,并感受到 Vite 和 Svelte 带来的开发体验优化。那接下来看看这套方案在实际项目中的性能表现。

为了对比 Svelte 和 Vue 之间的性能差异,我特地找了一个小型项目进行改造,用 Svelte 对它重写,并通过 ABTest 进行线上的性能数据对比。

5.1 首先,来看打包之后的 bundle 大小对比

Vue 的包体

图片

Svelte 的包体

图片

是否压缩

Vue

Svelte

差值

gzip 前

360K

207K

降低 42.5%

gzip 后

124K

77K

降低 38%

可以看到 Svelte 相比于 Vue,在包体大小上确实优化了不少,基本在40%左右,效果很明显。

5.2 其次,看看本地的启动速度(FCP)对比

在本地进行10次平均性能测试,发现 Svelte 的 FCP 指标比 Vue 要快了约46%,说明 Svelte 的首屏渲染速度比 Vue 快了不少,提升很明显。

_

Vue

Svelte

FCP(ms)

1128

738

FCP(ms)

1897

545

FCP(ms)

990

701

FCP(ms)

1016

608

FCP(ms)

1002

620

FCP(ms)

1391

587

FCP(ms)

1294

662

FCP(ms)

983

803

FCP(ms)

1231

618

FCP(ms)

1279

757

FCP 均值(ms)

1234.7

663.9

优化程度(%)

-

46.2% ↑

下面这个录屏是对比两个页面首次打开时的效果,左侧为 Svelte,右侧为 Vue。

图片

5.3 最后,看看线上的启动速度数据对比 

我们通过 ABTest 进行线上的启动速度数据对比,在投放了1周后,数据结论如下:

图片



平均启动速度

vue

2493 ms

svelte

2132 ms

差值

361 ms

优化程度

14.5% ↑

以看到 Svelte 在线上的启动速度表现也比 Vue 要快一些,优化程度约为14.5%。

注意:这里的平均启动速度指标是我们团队内部定义的页面启动速度指标,计算方式:业务启动速度 = 页面加载完成时间 - 页面入口点击时间。由于我们是在客户端 App 中进行测试,因此该时间包含了客户端 webview 的启动时间。所以实际上 Svelte 对前端部分的启动速度优化程度可能会更高,参考前面的 FCP 指标的本地测试结果。

总之,对于小型项目,Svelte 在包体大小和启动速度上还是有不少提升的,如果你的项目对启动速度有强要求,也可以尝试使用 Svelte 来开发或改造,应该会有不错的效果。

六、Svelte 比 Vue 快在哪?

通过上面的数据分析,虽然我们了解到 Svelte 在构建小型项目时确实有更快的页面启动速度,但具体快在哪,还需要进一步深入分析。

我们可以通过 Chrome 的 devtool 来观察 Svelte 和 Vue 两者打包后的页面在加载流程上的差异。

Vue 页面加载流程

图片

Svelte 页面加载流程

图片

对比二者的加载流程,可以看到耗时上有两个主要的差异点:



耗时差异





Vue





Svelte



JS Bundle 加载时间

627 ms

274 ms

Html/JS 解析耗时

292 + 148 + 85 = 525ms

290 ms

因此,在小型项目中,Svelte 相比于 Vue,有两个明显的优势:

  • 资源加载更快:由于包体较小,所以加载首屏 JS  Bundle 时网络耗时更短。
  • Html/JS解析执行更快:由于 Svelte 几乎无运行时,因此在执行相同业务逻辑时,解析执行耗时更短。并且在解析执行过程中,没有二次加载更多的首屏 JS、CSS 资源,因此整体的解析执行速度更快。

七、总结

总之,对于小型项目而言,Vite + Svelte 这对组合还是很不错的,既提升了开发效率,又优化了页面性能,更加“小巧灵动”。而且这两者的学习曲线都比较缓和,基本在2-3天内就可以完成学习加一个简单项目的改造。

一点题外话,很多时候大家会低估“技术尝新”的重要性,我们被困在团队圈定的“技术穹顶”中,永远用一个“套路”去实现所有业务,这会让我们感到疲乏、缺乏价值感和动力,甚至影响工作的投入程度,久而久之,整个团队也会在技术上变得迟滞。

所以在有机会时,要尽量合理地发掘和尝试新的技术方案,一方面是让自己保持技术活力,另一方面也是在加强团队的技术沉淀。

责任编辑:庞桂玉 来源: vivo互联网技术
相关推荐

2009-05-04 09:13:12

K-MeleonCCF浏览器

2022-08-09 10:00:57

ViteTypeScripVue3

2022-01-17 11:41:50

前端Vite组件

2022-09-30 09:33:55

ViteCLI

2024-09-30 09:35:55

图像生成AI

2012-04-17 09:55:29

云计算分布式

2023-11-17 08:01:30

Vite 5前端

2024-01-09 18:00:22

Rust后端slvelte

2010-02-25 15:22:02

2024-11-28 10:26:32

2022-07-12 18:00:00

MySQL模式高可用

2022-07-12 19:00:00

数据库MySQL

2011-05-07 11:25:09

激光打印机

2023-09-19 13:11:26

自动驾驶研究

2022-08-31 06:37:34

Vue 3模板

2019-12-11 14:10:44

微信朋友网腾讯

2012-03-19 10:49:21

ibmdw

2010-05-04 15:41:44

交换负载均衡
点赞
收藏

51CTO技术栈公众号