- VisualStudio2022插件的安装及使用-编程手把手系列文章
- pprof-在现网场景怎么用
- C#实现的下拉多选框,下拉多选树,多级节点
- 【学习笔记】基础数据结构:猫树
作者:来自 vivo 互联网大前端团队- Wei Xing 。
在研发小型项目时,传统的 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,详情可参考尤雨溪尤大本人针对 Svelte 和 Vue3的包体大小问题的分析.
理论上在普通 CSR 项目中,组件数量超过19个时, Svelte 就失去了它的包体大小优势.
先了解下 Vite 和 Svelte.
Vite 是尤雨溪尤大写的一款高效的前端构建工具,相比于 Webpack,它最大的优势就是“快”.
在开发环境下,Vite 使用高性能的 Esbuild 来进行预构建,并利用现代浏览器对 ESM 的支持,直接将预构建好的ES模块丢给浏览器进行解析执行,无需在每次变更代码时都重新编译代码,具有更快的冷启动速度和热更新效率.
在生产环境下,Vite 基于 Rollup 进行打包,Rollup 同样支持 ESM 语法,并且具有更快速高效的 Treeshaking,一般情况下,Rollup 具有更小的包体大小和更快的构建速度.
参考 github 上的构建工具横向对比 benchmark.
(图片来源:https://github.com) 。
可以看到无论是冷启动、热更新还是生产环境打包,Vite 都是优于 Webpack 的。尤其是在开发过程中的热更新很快,大大优化了开发体验.
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 的项目.
通过 npm 全局安装 Vite:
npm install vite -g
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 ↗
通过以下命令运行项目:
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 两个配置文件.
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 分别在开发体验上带来的一些优化.
首先,Vite 的开发体验太棒了。它的构建速度极快,对开发效率有很明显的提升.
在开发环境下,Webpack 每次都需要对改动的部分进行重新编译打包,耗时几秒钟,而 Vite 则不需要重新打包,只需要把更新后的 ESM 代码交付给浏览器就ok,几乎是即时更新.
同时在构建生产环境包时,也明显比原先的 Vue 项目要快了近50%。别小看这一点速度的提升,让整个开发体验好了不少.
如果你跟随上面步骤搭建了项目,那你可以打开项目中的 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 带来的开发体验上的一些优化.
上面我们了解了如何搭建 Vite+Svelte 项目,并感受到 Vite 和 Svelte 带来的开发体验优化。那接下来看看这套方案在实际项目中的性能表现.
为了对比 Svelte 和 Vue 之间的性能差异,我特地找了一个小型项目进行改造,用 Svelte 对它重写,并通过 ABTest 进行线上的性能数据对比.
Vue 的包体:
Svelte 的包体:
可以看到 Svelte 相比于 Vue,在包体大小上确实优化了不少,基本在40%左右,效果很明显.
在本地进行10次平均性能测试,发现 Svelte 的 FCP 指标比 Vue 要快了约46%,说明 Svelte 的首屏渲染速度比 Vue 快了不少,提升很明显.
下面这个录屏是对比两个页面首次打开时的效果,左侧为 Svelte,右侧为 Vue.
。
我们通过 ABTest 进行线上的启动速度数据对比,在投放了1周后,数据结论如下:
可以看到 Svelte 在线上的启动速度表现也比 Vue 要快一些,优化程度约为14.5%.
注意:这里的平均启动速度指标是我们团队内部定义的页面启动速度指标,计算方式:业务启动速度 = 页面加载完成时间 - 页面入口点击时间。由于我们是在客户端 App 中进行测试,因此该时间包含了客户端 webview 的启动时间。所以实际上 Svelte 对前端部分的启动速度优化程度可能会更高,参考前面的 FCP 指标的本地测试结果.
总之,对于小型项目,Svelte 在包体大小和启动速度上还是有不少提升的,如果你的项目对启动速度有强要求,也可以尝试使用 Svelte 来开发或改造,应该会有不错的效果.
通过上面的数据分析,虽然我们了解到 Svelte 在构建小型项目时确实有更快的页面启动速度,但具体快在哪,还需要进一步深入分析.
我们可以通过 Chrome 的 devtool 来观察 Svelte 和 Vue 两者打包后的页面在加载流程上的差异.
Vue 页面加载流程:
Svelte 页面加载流程:
对比二者的加载流程,可以看到耗时上有两个主要的差异点:
因此,在小型项目中,Svelte 相比于 Vue,有两个明显的优势:
资源加载更快:由于包体较小,所以加载首屏 JS Bundle 时网络耗时更短.
Html/JS解析执行更快:由于 Svelte 几乎无运行时,因此在执行相同业务逻辑时,解析执行耗时更短。并且在解析执行过程中,没有二次加载更多的首屏 JS、CSS 资源,因此整体的解析执行速度更快.
总之,对于小型项目而言,Vite + Svelte 这对组合还是很不错的,既提升了开发效率,又优化了页面性能,更加“小巧灵动”。而且这两者的学习曲线都比较缓和,基本在2-3天内就可以完成学习加一个简单项目的改造.
一点题外话,很多时候大家会低估“技术尝新”的重要性,我们被困在团队圈定的“技术穹顶”中,永远用一个“套路”去实现所有业务,这会让我们感到疲乏、缺乏价值感和动力,甚至影响工作的投入程度,久而久之,整个团队也会在技术上变得迟滞.
所以在有机会时,要尽量合理地发掘和尝试新的技术方案,一方面是让自己保持技术活力,另一方面也是在加强团队的技术沉淀.
最后此篇关于主打一个“小巧灵动”:Vite+Svelte的文章就讲到这里了,如果你想了解更多关于主打一个“小巧灵动”:Vite+Svelte的内容请搜索CFSDN的文章或继续浏览相关文章,希望大家以后支持我的博客! 。
我看了你的文章 https://svelte.dev/blog/virtual-dom-is-pure-overhead和其他一些博客,但它们解释了与虚拟 dom 相比,svelte 如何更好。而我想
我正在尝试制作一个 Svelte 应用程序,其中我有一个创建 audioSource 并管理它的类(不是 svelte 组件)。 我想跨多个组件获取此类实例。 现在,我发现的唯一方法是这样做:
我有一个案例,我打开了两个选项卡 localhost:5000/和localhost:5000/stream并想更新 / 中的变量路径并查看 stream 中的更改实时路径。存储不是这样工作的,如果我
我正在尝试创建一个带有客户端文件输入的网站,其中一些数据完全在客户端上处理,并且不会发送到服务器。 我有以下 Svelte 组件 (App.svelte): let data; function h
我正在尝试创建一个带有客户端文件输入的网站,其中一些数据完全在客户端上处理,并且不会发送到服务器。 我有以下 Svelte 组件 (App.svelte): let data; function h
我正在研究 Svelte,并从其 Github 存储库中克隆了它。我可以从站点目录运行 REPL,但它使用来自 unpkg url 的 Svelte。我想尝试我本地构建的编译器并使用它而不是 unpk
我想将样式添加到 在纤细路由中标记,但我不能。 我试图添加一个有一些样式的类,但它没有用。 该类包含: .link { text-decoration: none; } 有没有人对此有解决方案
目前,当我在浏览器中打开开发人员工具时,我可以看到我的原始 svelte 组件,我想隐藏此信息并仅发送丑陋的代码。 这是我打开开发者工具时得到的。我正在构建一个单页应用程序。 这是我的 rollup.
我目前正在学习 Svelte,我想为这个副项目创建一个身份验证流程。通常,在 React 中,我习惯使用 Contexts 保存身份验证信息。 我想知道 Svelte 是否也可以执行类似的
调用 new Component({ target }) 将组件附加到目标,我想用新组件替换目标的所有旧内容。我该怎么做? 最佳答案 如果您正在混合服务器呈现的标记,最好使用 hydrate: tru
我有一个简单的 REPL example用于简单的列表详细信息编辑器。它由三个部分组成: Annotation是细节 Annotations遍历数据并创建 Annotation实例 App是创建 An
我正尝试在 Svelte 商店中维护实时股票报价,以便屏幕上的出价和要价实时更新。我不确定商店的结构如何来保持数据的 react 性和效率。数据来自 websocket,如下所示: {'symbol'
下面是一个非常简单的 Svelte 组件。 当您单击该按钮时,它会更新 pages[2].name。 Svelte 如何处理这个问题?它是否重新评估所有 3 个 DIV?或者它是否知道只修改第 3 个
我制作了一个用于输入财务数字的组件,用于我的输入表单。它现在工作得很好,除了一个奇怪的行为:当我点击输入字段时,它会按预期获得焦点,但是当它已经有焦点时点击它会带走焦点。 组件中只有一个 on:cli
我尝试实现一个自定义的 Svelte 商店,它允许我在订阅页面上“抛出”一个单一的状态对象。这是我准备的示例代码: import { derived, writable } from 'svelte/
我正在尝试安装带有 Svelte 的 Mermaid 来制作图表。所以我做了以下事情: npm 安装美人鱼 然后我得到以下内容: npm WARN svelte-app@1.0.0 No reposi
如何渲染使用 svelte.compile() 手动编译的组件?我正在编译这样的组件: import * as svelte from 'svelte/compiler'; var
我正在学习 Svelte 以及如何使用它制作自定义商店。我遇到了一个问题,当我尝试使用 update 更新可写数组时,它会在订阅该数组的组件中导致未定义的错误。 这是我的商店,我有一个简单的数组,其中
我正在尝试遍历数组以呈现具有 type 值的组件。 import One from './One.svelte'; import Two from './Two.svelte'; import
如何将数据(例如:导航栏标题)传递给父元素中使用的组件? import Nav from "../components/Nav.svelte"; let navTitle = "MyApp
我是一名优秀的程序员,十分优秀!