首頁  >  文章  >  收藏這些vue專案效能優化方式,總有一天能用!

收藏這些vue專案效能優化方式,總有一天能用!

青灯夜游
青灯夜游轉載
2022-04-29 11:04:174322瀏覽

vue專案如何進行效能最佳化?以下這篇文章跟大家分享一些vue專案一定會用到的效能最佳化方法,希望對大家有幫助!

收藏這些vue專案效能優化方式,總有一天能用!

提起效能優化 很多人眼前浮現的面試經驗是不是歷歷在目呢?反正,效能優化在我看來他永遠是前端領域的熱度之王

而本渣最近維護的專案恰巧在這個方向下了很大功夫,一些經驗之談奉上,希望對大家有些許幫助!

效能最佳化標準


既然說效能最佳化,那他總得有一個公認的標準,這就是我們很多次聽到的Lighthouse

收藏這些vue專案效能優化方式,總有一天能用!

在許多單位,都有自己的效能監控平台,我們只需要引進對應的sdk,那麼在平台上就能分析出你頁面的存在的效能問題,大家是不是學的很神奇!

其實除了苛刻的業務,需要特殊的客製化,大多數的情況下我們單位的效能優化平臺本質上其實就是利用無頭瀏覽器(Puppeteer)跑 Lighthouse

了解我們單位的效能監控平台的原理之後,我們就能針對性的做效能最佳化,也就是面向Lighthouse程式設計

Lighthouse

lighthouse 是Google Chrome 推出的開源自動化工具,它可以蒐集多個現代網頁效能指標,分析Web 應用的效能並產生報告,為開發人員進行效能優化的提供了參考方向。

說起Lighthouse在現代的谷歌瀏覽器中業已經集成

收藏這些vue專案效能優化方式,總有一天能用!

他可以分析出我們的頁面性能,通過幾個指標

Lighthouse 會衡量以下效能指標項目:

在一般情況下,根據我的經驗,由於效能監控平台的和本地平台的

差異,本地可能要達到70分,線上才有可能達到及格的狀態,如果有性能優化的需求時,大家酌情處理即可(不過本人覺得,及格即可, 畢竟大學考試有曰:60分萬歲,61分浪費,傳承不能丟,咱們要把更多的時間,放到更重要的事情上來!)

通用常規優化手段


lighthouse的的牛x之處就是它能找出你頁面中的一些常規的效能瓶頸,並提出最佳化建議,例如:

收藏這些vue專案效能優化方式,總有一天能用!

收藏這些vue專案效能優化方式,總有一天能用!

於是針對這些最佳化建議,我們需要做一些常規的最佳化:

  • 減少未使用的javascript

  • 移出阻塞渲染的資源

  • 圖片品質壓縮

  • #限制使用字體數量,盡可能少使用變體

  • 優化關鍵渲染路徑:只載入目前頁面渲染所需的必要資源,將次要資源放在頁面渲染完成後載入

通用效能最佳化分析


我們知道lighthouse 中有六個效能指標,而在這六個指標中,LCP、 FCP、speed index、 這三個指數特別重要,因為在一般情況下這個三個指標會影響TTI、TBT、CLS 的分數

所以在我們在優化時,需要提高LCP、 FCP和speedIndex 的分數,經過測試, 即使是空頁面也會有時間上的損耗, 初始分數基本上都是0.8

注意: 需要值得大家注意的是,我們目前所有測試全部建立在,行動端(之所以用行動端,是由於pc 的強大算力,很少有性能瓶頸)的基礎上,並且頁面上必須有一下內容,才能得出分數,內容必須包含一下的一種或多種

  • 內嵌在svg元素內的image元素
  • video元素(使用封面圖片)
  • 透過url()函數(而非使用CSS 漸層)載入的背景圖像的元素
  • 包含文字節點或其他行內級文字元素子元素的區塊級元素

否則就會有以下錯誤

收藏這些vue專案效能優化方式,總有一天能用!

接下來我們就從LCP、 FCP和speedIndex 這三個指標入手

FCP(First Contentful Paint)

顧名思義就是首次內容繪製,也就是頁面最開始繪製內容的時間,但由於我們現在開發的頁面都是spa應用,所以,框架層面的初始化是一定會有一定的效能損耗的,以vue-cli 搭建的鷹架為例,當我初始化空的鷹架,打包後上傳cdn部署,FCP 就會從0.8s提上到1.5秒,由此可見vue 的diff 也不是免費的他也會有效能上的損耗。 (學習影片分享:vuejs教學

在優化頁面的內容之前我們聲明三個前提

  • 提高FCP的時間其實就是在優化關鍵渲染路徑

  • 如果它是樣式檔案(CSS檔案),瀏覽器必須在渲染頁面之前完全解析它(這就是為什麼說CSS具有渲染阻礙性)

  • 如果它是一個腳本檔案(JavaScript檔案),瀏覽器必須: 停止解析,下載腳本,並執行它。只有在這之後,它才能繼續解析,因為 JavaScript 腳本可以改變頁面內容(特別是HTML)。 (這就是為什麼說JavaScript阻塞解析)

針對以上的用例測試,我們發現,無論我們怎麼優化,框架本身的效能損耗是無法抹除的,我們唯一能做的就是讓框架更早的去執行初始化,並且初始化更少的內容,可做的優化手段如下:

  • 所有初始化用不到的js 檔案全部走異步加載,也就是加上deferasnyc ,並且一些需要走cdn的第三方外掛程式需要放在頁面底部(因為放在頂部,他的解析會阻止html 的解析,從而影響css 等檔案的下載,這也是雅虎軍規的一條)

  • js 檔案拆包,以vue-cli 為例,一般情況下我們可以透過cli的設定splitChunks 做程式碼分割,將一些第三方的套件走cdn,或是拆包。如果有路由的情況下將路由做拆包處理,確保每個路由只載入目前路由對應的js程式碼

  • #最佳化檔案大小減少字型包、 css檔、以及js檔的大小(當然這些腳手架預設都已經做了)

  • 優化專案結構,每個元件的初始化都是有效能損耗的,在保證可維護性的基礎上,盡量減少初始化元件的載入數量

  • 網路協定層面的最佳化,這個最佳化手段需要服務端配合純前端已經無法達到,在現在雲端伺服器盛行的時代,自家單位通常會預設在雲端伺服器中開啟這些最佳化手段,例如開啟gzip,使用cdn 等等

##其實來說去,提高FCP 的核心只有理念之後兩個

減少初始化視圖內容 減少初始化下載資源大小

LCP(Largest Contentful Paint)

顧名思義就是

最大內容繪製, 何時報告LCP,官方是這樣說的

為了應對這種潛在的變化,瀏覽器會在繪製第一幀後立即分發一個

largest-contentful-paint類型的#PerformanceEntry,用於識別最大內容元素。但是,在渲染後續影格之後,瀏覽器會在最大內容元素變更時分發另一個PerformanceEntry

例如,在一個帶有文字和首圖的網頁上,瀏覽器最初可能只渲染文字部分,並在此期間分發一個

largest-contentful-paint條目,其element屬性通常會引用一個

 。隨後,一旦首圖完成加載,瀏覽器就會分發第二個largest-contentful-paint條目,其element屬性將引用收藏這些vue專案效能優化方式,總有一天能用!要注意的是,一個元素只有在渲染完成並且對使用者可見後才能被視為最大內容元素。尚未載入的圖像不會被視為"渲染完成"。在

字體阻塞期使用網頁字體的文字節點也是如此。在這種情況下,較小的元素可能會被報告為最大內容元素,但一旦更大的元素完成渲染,就會透過另一個PerformanceEntry物件進行報告。

其實大白話解釋就是,通常情況下,

圖片、影片以及大量文字繪製完成後就會報告LCP

理解了這一點,的最佳化手段就明確了,盡量減少這些資源的大小就可以了,經過測試,減少首屏渲染的圖片以及視頻內容大小後,整體分數顯著提高,提供一些優化方法:

  • 本地圖片可以使用線上壓縮工具自行壓縮建議:

    https://tinypng.com/

  • #介面中附帶圖片,一般情況下單位中都有對應的oss或cdn傳參配置透過網址列傳參方式控制圖片品質

  • 圖片懶載入

SpeedIndex(速度指數)

Speed Index採用視覺頁面載入的視覺進度,計算內容繪製速度的總分。為此,首先需要能夠計算在頁面載入期間,各個時間點「完成」了多少部分。在WebPagetest中,透過捕捉在瀏覽器中載入頁面的影片並檢查每個影片畫面(在啟用影片擷取的測試中,每秒10幀)來完成的,這個演算法在下面有描述,但現在假設我們可以為每個視訊幀分配完整的百分比(在每個幀下顯示的數字)

以上是官方解釋的計算方式,其實通俗的將,所謂速度指數就是衡量頁面內容填充的速度

收藏這些vue專案效能優化方式,總有一天能用!

一圖勝千言

經過測試,跟LCP相同,圖片以及影片內容對於SpeedIndex的影響巨大,所有優化方向,通之前一致,總的來說,只要提高LCP 以及FCP 的時間SpeedIndex 的時間就會有顯著提高

不過需要注意的是,接口的速度也會影響SpeedIndex的時間,由於AJAX流行的今天,我們大多數的資料都是使用介面拉取。如果介面速度過慢,他就會影響你頁面的初始渲染, 導致效能問題,所以,在做效能優化的同時,

請求後端夥伴協助,也是效能最佳化的一個方案

#排查效能瓶頸#

上述分析,根據三個指標提供了一些常規的優化手段,那麼在這些優化手段中,有的你可以立刻排查到,並且優化例如:

  • 優化圖片,最佳化字體大小

  • 跟服務端配合利用瀏覽器快取機制.啟用cdn、啟用gzip等

  • 減少網路協定過程中的消耗,減少http 請求、減少dns查詢、避免重定向

  • 優化關鍵渲染路徑,異步載入js等

但是有的優化手段我們不容易排查,因為他是打在包包裡面的,這個js 檔案包含了很多邏輯怎麼辦,這裡我有兩個手段或許能夠幫忙排查出效能瓶頸發生在哪裡:

分析套件內容

在通常情況下,我們無法判斷的最佳化點,都是在打包後,我們無法分析出,那些東西不是我們在首屏必須需要的,從而不能做出針對新的最佳化,為了解決目前問題,各大bundle廠商也都有各自的分析套件的方案

#以vue-cli 為例

"report": "vue-cli-service build --report"

我們只需要在鷹架中提供以上指令,就能在打包時生成,整個包的分析檔

收藏這些vue專案效能優化方式,總有一天能用!

#如上圖所示在打包後就能分析出打包後的js 檔案他包含什麼元件,如此以來,我們就能知道那些檔案是沒必要同步載入的,或是走cdn的,透過設定將他單獨的隔離開來,從而找出效能的問題

##利用chorme devtool 的程式碼覆蓋率

如下圖所示,

收藏這些vue專案效能優化方式,總有一天能用!

#利用devtool的程式碼覆蓋率檢查就能知道那些js 或css 檔案的程式碼沒有被使用過,結合包內容的分析,我們就能大概的猜出性能的瓶頸在哪裡從而做相應的特殊處理

##針對vue 的特殊優化

以上內容都是通用的一些優化手段,您在哪裡都能查到,只是我表達了一下做這些常規優化的深層原因。能讓您更清楚的了解這些原因之後,
在性能瓶頸的時候能游刃有餘,而不是為了面試死記硬背,一到用的時候就不靈


然後我司是vue啊,咱得上得vue 的手段

圖片懶加載所謂圖片懶加載,就是頁面只渲染目前可視區域內的圖片,如此一來,減少了其他圖片渲染數量,能大大提高

SpeedIndex

LCP的時間,從而提高分數

在vue中提起圖片懶加載插件,首推:vue-lazyload

    #https://github.com/hilongjw/vue-lazyload
#使用方式簡單,功能豐富

虛擬滾動#在一含有長列表頁面中,你有沒有發現你是往下越滑越卡,此時虛擬滾動就排上用場了, 他的基本原理就是只渲染可視區域內的幾條數據,但是模擬出正常滑動的效果,因為每次只渲染可是劇域內的數據,在滑動的時候他的性能就會有飛速提升

在vue中比較好用的外掛有兩個:

    vue-virtual-scroller :https://github.com/Akryum/vue-virtual- scroller
  • vue-virtual-scroll-list :https://github.com/tangbc/vue-virtual-scroll-list
##目前我司統一用的vue-virtual-scroll-list 他下拉的時候到了分頁的地方能加些loading提示

vue 中的函數式元件 在vue中我們知道元件的初始化是比較損耗效能的,大家可以去試一下,使用vue 直接渲染一個文字內容,和直接渲染一個app.vue 元件他的分數是略有不同的。

但是當有了函數式元件,這個問題就迎刃而解了

因為函數是元件顧名思義他就是個函數,說白了就是個

render函數

,他少了元件初始化的過程,省去了很多初始化過程的開銷

什麼時候用函數式元件呢?

當你的元件中沒有業務邏輯只展示內容時,這時候函數式元件就派上用場了

利用v-show 、KeepAlive 復用dom

我们知道v-show是通过display 控制dom的展示隐藏,他并不会删除dom 而我们在切换v-show的时候其实是减少了diff的对比,而KeepAlive 则是直接复用dom,连diff 的过程都没了,并且他们俩的合理使用还不会影响到初始化渲染。如此一来减少了js 的执行开销,但是值得注意的是,他并不能优化你初始化的性能,而是操作中的性能

分批渲染组件

在前面我们提到过SpeedIndex 的渐进渲染是提高SpeedIndex的关键,有了这个前提,我们就可以分批异步渲染组件。先看到内容,然后在渲染其他内容

举个例子:

<template>
    <div>
        {{ data1 }}
    </div>
    <div v-if="data1">
        {{ data2 }}
    </div>
</template>
<script>
import { ref } from &#39;vue&#39;
export default {
    setup() {
        let data1 = ref(&#39;&#39;)
        let data2 = ref(&#39;&#39;)
        // 假设 这是从后端取到的数据
        const data = {
            data1: &#39;这是渲染内容1&#39;,
            data2: &#39;这是渲染内容2&#39;
        }
        data1.value = data.data1
        //利用requestAnimationFrame 在空闲的时候当前渲染之后在渲染剩余内容
        requestIdleCallback(() => {
            data2.value = data.data2
        })
        return {
            data1,
            data2
        }
    },
}
</script>

上述例子比较简单可能描述的不太贴切,在这里特此说明一下,当前方法适用于组件内容较多,每次render 时间过长,导致白屏时间过长,比如,一次拉取用户列表,那么分批渲染就非常合适,先展示一部分用户信息,最后直到慢慢将所有内容渲染完毕。如此对浏览器的SpeedIndex 也非常友好

最后


性能优化一直是一个很火的话题, 不管从面试以及工作中都非常重要,有了这些优化的点,你在写代码或者优化老项目时都能游刃有余,能提前考虑到其中的一些坑,并且规避。

但是大家需要明白的是,不要为了性能优化而性能优化,我们在要因地制宜,在不破坏项目可维护性的基础上去优化,千万不要你优化个项目性能是好了,但是大家都看不懂了,这就有点得不偿失了,还是那句话,60分万岁61份浪费,差不多得了,把经历留着去干更重要的事情!

原文地址:https://juejin.cn/post/7089241058508275725

作者:好学习吧丶

(学习视频分享:web前端开发编程入门

陳述:
本文轉載於:juejin.cn。如有侵權,請聯絡admin@php.cn刪除