动态

详情 返回 返回

主打一個“小巧靈動”:Vite + Svelte - 动态 详情

作者:來自 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 和 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 的包體

圖片

可以看到 Svelte 相比於 Vue,在包體大小上確實優化了不少,基本在40%左右,效果很明顯。

5.2 其次,看看本地的啓動速度(FCP)對比

在本地進行10次平均性能測試,發現 Svelte 的 FCP 指標比 Vue 要快了約46%,説明 Svelte 的首屏渲染速度比 Vue 快了不少,提升很明顯。

下面這個錄屏是對比兩個頁面首次打開時的效果,左側為 Svelte,右側為 Vue。

圖片

5.3 最後,看看線上的啓動速度數據對比 

我們通過 ABTest 進行線上的啓動速度數據對比,在投放了1周後,數據結論如下:

圖片

可以看到 Svelte 在線上的啓動速度表現也比 Vue 要快一些,優化程度約為14.5%。

注意:這裏的平均啓動速度指標是我們團隊內部定義的頁面啓動速度指標,計算方式:業務啓動速度 = 頁面加載完成時間 - 頁面入口點擊時間。由於我們是在客户端 App 中進行測試,因此該時間包含了客户端 webview 的啓動時間。所以實際上 Svelte 對前端部分的啓動速度優化程度可能會更高,參考前面的 FCP 指標的本地測試結果。

總之,對於小型項目,Svelte 在包體大小和啓動速度上還是有不少提升的,如果你的項目對啓動速度有強要求,也可以嘗試使用 Svelte 來開發或改造,應該會有不錯的效果。

六、Svelte 比 Vue 快在哪?

通過上面的數據分析,雖然我們瞭解到 Svelte 在構建小型項目時確實有更快的頁面啓動速度,但具體快在哪,還需要進一步深入分析。

我們可以通過 Chrome 的 devtool 來觀察 Svelte 和 Vue 兩者打包後的頁面在加載流程上的差異。

Vue 頁面加載流程

圖片

Svelte 頁面加載流程

圖片

對比二者的加載流程,可以看到耗時上有兩個主要的差異點:

因此,在小型項目中,Svelte 相比於 Vue,有兩個明顯的優勢:

  • 資源加載更快:由於包體較小,所以加載首屏 JS  Bundle 時網絡耗時更短。
  • Html/JS解析執行更快:由於 Svelte 幾乎無運行時,因此在執行相同業務邏輯時,解析執行耗時更短。並且在解析執行過程中,沒有二次加載更多的首屏 JS、CSS 資源,因此整體的解析執行速度更快。

七、總結

總之,對於小型項目而言,Vite + Svelte 這對組合還是很不錯的,既提升了開發效率,又優化了頁面性能,更加“小巧靈動”。而且這兩者的學習曲線都比較緩和,基本在2-3天內就可以完成學習加一個簡單項目的改造。

一點題外話,很多時候大家會低估“技術嘗新”的重要性,我們被困在團隊圈定的“技術穹頂”中,永遠用一個“套路”去實現所有業務,這會讓我們感到疲乏、缺乏價值感和動力,甚至影響工作的投入程度,久而久之,整個團隊也會在技術上變得遲滯。

所以在有機會時,要儘量合理地發掘和嘗試新的技術方案,一方面是讓自己保持技術活力,另一方面也是在加強團隊的技術沉澱。

user avatar openfuyao 头像 u_15714439 头像 xuxueli 头像 geeklab 头像 _wss 头像 java_study 头像 coderleo 头像 flydean 头像 xiaoal 头像 wmuhua 头像 wisdomqq 头像 shuihuyangpinga 头像
点赞 24 用户, 点赞了这篇动态!
点赞

Add a new 评论

Some HTML is okay.