<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          分享一些在 VUE 項目中你可能會用上的性能優(yōu)化技巧

          共 8838字,需瀏覽 18分鐘

           ·

          2022-07-09 17:17

          提起性能優(yōu)化 很多人眼前浮現(xiàn)的面試經(jīng)驗是不是歷歷在目呢?反正,性能優(yōu)化在我看來他永遠(yuǎn)是前端領(lǐng)域的熱度之王

          最近維護(hù)的項目恰巧在這個方向下了很大功夫,一些經(jīng)驗之談奉上,希望對大家有些許幫助!

          性能優(yōu)化標(biāo)準(zhǔn)

          既然說性能優(yōu)化,那他總得有一個公認(rèn)的標(biāo)準(zhǔn),這就是我們很多次聽到的Lighthouse

          在很多單位,都有著自己的性能監(jiān)控平臺,我們只需要引入相應(yīng)的sdk,那么在平臺上就能分析出你頁面的存在的性能問題,大家是不是學(xué)的很神奇!

          其實除了苛刻的業(yè)務(wù),需要特殊的定制,大多數(shù)的情況下我們單位的性能優(yōu)化平臺本質(zhì)上其實就是利用無頭瀏覽器(Puppeteer)跑Lighthouse

          理解了我們單位的性能監(jiān)控平臺的原理之后,我們就能針對性的做性能優(yōu)化,也就是面向Lighthouse編程

          Lighthouse

          lighthouse[1] 是 Google Chrome 推出的一款開源自動化工具,它可以搜集多個現(xiàn)代網(wǎng)頁性能指標(biāo),分析 Web 應(yīng)用的性能并生成報告,為開發(fā)人員進(jìn)行性能優(yōu)化的提供了參考方向。

          說起Lighthouse在現(xiàn)代的谷歌瀏覽器中業(yè)已經(jīng)集成

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

          Lighthouse 會衡量以下性能指標(biāo)項:

          • 首次內(nèi)容繪制[2](First Contentful Paint)。即瀏覽器首次將任意內(nèi)容(如文字、圖像、canvas 等)繪制到屏幕上的時間點。
          • 可交互時間[3](Time to Interactive)。指的是所有的頁面內(nèi)容都已經(jīng)成功加載,且能夠快速地對用戶的操作做出反應(yīng)的時間點。
          • 速度指標(biāo)[4](Speed Index)。衡量了首屏可見內(nèi)容繪制在屏幕上的速度。在首次加載頁面的過程中盡量展現(xiàn)更多的內(nèi)容,往往能給用戶帶來更好的體驗,所以速度指標(biāo)的值約小越好。
          • 總阻塞時間[5](Total Blocking Time)。指First Contentful Paint 首次內(nèi)容繪制 (FCP)與Time to Interactive 可交互時間 (TTI)之間的總時間
          • 最大內(nèi)容繪制[6](Largest Contentful Paint)。度量標(biāo)準(zhǔn)報告視口內(nèi)可見的最大圖像或文本塊的呈現(xiàn)時間
          • 累積布局偏移[7](# Cumulative Layout Shift)。衡量的是頁面整個生命周期中每次元素發(fā)生的非預(yù)期布局偏移得分的總和。每次可視元素在兩次渲染幀中的起始位置不同時,就說是發(fā)生了LS(Layout Shift)。

          在一般情況下,據(jù)我的經(jīng)驗,由于性能監(jiān)控平臺的和本地平臺的差異,本地可能要達(dá)到70分,線上才有可能達(dá)到及格的狀態(tài),如果有性能優(yōu)化的需求時,大家酌情處理即可(不過本人覺得,及格即可, 畢竟大學(xué)考試有曰:60分萬歲,61分浪費,傳承不能丟,咱們要把更多的時間,放到更重要的事情上來!)

          通用常規(guī)優(yōu)化手段

          lighthouse的的牛x之處就是它能找出你頁面中的一些常規(guī)的性能瓶頸,并提出優(yōu)化建議,比如:

          于是針對這些優(yōu)化建議,我們需要做一些常規(guī)的優(yōu)化:

          1. 減少未使用的javascript
          2. 移出阻塞渲染的資源
          3. 圖片質(zhì)量壓縮
          4. 限制使用字體數(shù)量,盡可能少使用變體
          5. 優(yōu)化關(guān)鍵渲染路徑:只加載當(dāng)前頁面渲染所需的必要資源,將次要資源放在頁面渲染完成后加載

          通用性能優(yōu)化分析

          我們知道lighthouse 中有六個性能指標(biāo),而在這六個指標(biāo)中,LCP、 FCP、speed index、 這三個指數(shù)尤為重要,因為在一般情況下 這個三個指標(biāo)會影響 TTI、TBT、CLS 的分?jǐn)?shù)

          所以在我們在優(yōu)化時, 需要提高LCP、 FCP和speedIndex 的分?jǐn)?shù),經(jīng)過測試, 即使是空頁面也會有時間上的損耗, 初始分?jǐn)?shù)基本都是0.8

          注意:需要值得大家注意的是,我們當(dāng)前所有測試全部建立在,移動端(之所以用移動端,是由于pc 的強大算力,很少有性能瓶頸)的基礎(chǔ)上,并且頁面上必須有一下內(nèi)容,才能得出分?jǐn)?shù),內(nèi)容必須包括一下的一種或者多種

          • 內(nèi)嵌在svg元素內(nèi)的image元素
          • video元素(使用封面圖像)
          • 通過url()[8]函數(shù)(而非使用CSS 漸變[9])加載的帶有背景圖像的元素
          • 包含文本節(jié)點或其他行內(nèi)級文本元素子元素的塊級元素[10]

          否則就會有如下錯誤

          接下來我們就從LCP、 FCP和speedIndex 這三個指標(biāo)入手

          FCP(First Contentful Paint)

          顧名思義就是首次內(nèi)容繪制,也就是頁面最開始繪制內(nèi)容的時間,但是由于我們現(xiàn)在開發(fā)的頁面都是spa應(yīng)用,所以,框架層面的初始化是一定會有一定的性能損耗的,以vue-cli 搭建的腳手架為例,當(dāng)我初始化空的腳手架,打包后上傳cdn部署,F(xiàn)CP 就會從0.8s提上到1.5秒,由此可見vue 的diff 也不是免費的他也會有性能上的損耗

          在優(yōu)化頁面的內(nèi)容之前我們聲明三個前提

          1. 提高FCP的時間其實就是在優(yōu)化關(guān)鍵渲染路徑[11]
          2. 如果它是一個樣式文件(CSS文件),瀏覽器就必須在渲染頁面之前完全解析它(這就是為什么說CSS具有渲染阻礙性)
          3. 如果它是一個腳本文件(JavaScript文件),瀏覽器必須:停止解析,下載腳本,并運行它。只有在這之后,它才能繼續(xù)解析,因為 JavaScript 腳本可以改變頁面內(nèi)容(特別是HTML)。(這就是為什么說JavaScript阻塞解析)

          針對以上的用例測試,我們發(fā)現(xiàn),無論我們怎么優(yōu)化,框架本身的性能損耗是無法抹除的,我們唯一能做的就是讓框架更早的去執(zhí)行初始化,并且初始化更少的內(nèi)容,可做的優(yōu)化手段如下:

          1. 所有初始化用不到的js 文件全部走異步加載,也就是加上defer或者asnyc ,并且一些需要走cdn的第三方插件需要放在頁面底部(因為放在頂部,他的解析會阻止html 的解析,從而影響css 等文件的下載,這也是雅虎軍規(guī)的一條)

          2. js 文件拆包,以vue-cli 為例,一般情況下我們可以通過cli的配置 splitChunks 做代碼分割,將一些第三方的包走cdn,或者拆包。如果有路由的情況下將路由做拆包處理,保證每個路由只加載當(dāng)前路由對應(yīng)的js代碼

          3. 優(yōu)化文件大小 減少字體包、css文件、以及js文件的大小(當(dāng)然這些 腳手架默認(rèn)都已經(jīng)做了)

          4. 優(yōu)化項目結(jié)構(gòu),每個組件的初始化都是有性能損耗的,在在保證可維護(hù)性的基礎(chǔ)上,盡量減少初始化組件的加載數(shù)量

          5. 網(wǎng)絡(luò)協(xié)議層面的優(yōu)化,這個優(yōu)化手段需要服務(wù)端配合純前端已經(jīng)無法達(dá)到,在現(xiàn)在云服務(wù)器盛行的時代,自家單位一般都會默認(rèn)在云服務(wù)器中開啟這些優(yōu)化手段,比如開啟gzip,使用cdn 等等

          其實說來說去,提高FCP 的核心只有理念之后兩個 減少初始化視圖內(nèi)容和 減少初始化下載資源大小

          LCP(Largest Contentful Paint)

          顧名思義就是最大內(nèi)容繪制, 何時報告LCP,官方是這樣說的

          為了應(yīng)對這種潛在的變化,瀏覽器會在繪制第一幀后立即分發(fā)一個largest-contentful-paint類型的 PerformanceEntry[12],用于識別最大內(nèi)容元素。但是,在渲染后續(xù)幀之后,瀏覽器會在最大內(nèi)容元素發(fā)生變化時分發(fā)另一個PerformanceEntry

          例如,在一個帶有文本和首圖的網(wǎng)頁上,瀏覽器最初可能只渲染文本部分,并在此期間分發(fā)一個largest-contentful-paint條目,其element屬性通常會引用一個<p><h1> 。隨后,一旦首圖完成加載,瀏覽器就會分發(fā)第二個largest-contentful-paint條目,其element屬性將引用<img> 。

          需要注意的是,一個元素只有在渲染完成并且對用戶可見后才能被視為最大內(nèi)容元素。尚未加載的圖像不會被視為"渲染完成"。在字體阻塞期[13]使用網(wǎng)頁字體的文本節(jié)點亦是如此。在這種情況下,較小的元素可能會被報告為最大內(nèi)容元素,但一旦更大的元素完成渲染,就會通過另一個PerformanceEntry對象進(jìn)行報告。

          其實用大白話解釋就是,通常情況下,圖片、視頻以及大量文本繪制完成后就會報告LCP

          理解了這一點,的優(yōu)化手段就明確了,盡量減少這些資源的大小就可以了,經(jīng)過測試,減少首屏渲染的圖片以及視頻內(nèi)容大小后,整體分?jǐn)?shù)顯著提高,提供一些優(yōu)化方法:

          1. 本地圖片可以使用在線壓縮工具自己壓縮 推薦tinypng.com[14]
          2. 接口中附帶圖片,一般情況下單位中都有對應(yīng)的oss或者cdn傳參配置通過地址欄傳參方式控制圖片質(zhì)量
          3. 圖片懶加載

          SpeedIndex(速度指數(shù))

          Speed Index采用可視頁面加載的視覺進(jìn)度,計算內(nèi)容繪制速度的總分。為此,首先需要能夠計算在頁面加載期間,各個時間點“完成”了多少部分。

          在WebPagetest中,通過捕獲在瀏覽器中加載頁面的視頻并檢查每個視頻幀(在啟用視頻捕獲的測試中,每秒10幀)來完成的,這個算法在下面有描述,但現(xiàn)在假設(shè)我們可以為每個視頻幀分配一個完整的百分比(在每個幀下顯示的數(shù)字)

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

          一圖勝千言

          經(jīng)過測試,跟LCP相同,圖片以及視頻內(nèi)容對于SpeedIndex的影響巨大,所有優(yōu)化方向,通之前一致,總的來說,只要提高LCP 以及FCP 的時間SpeedIndex 的時間就會有顯著提高

          不過需要注意的是,接口的速度也會影響SpeedIndex的時間,由于AJAX流行的今天,我們大多數(shù)的數(shù)據(jù)都是使用接口拉取。如果接口速度過慢,他就會影響你頁面的初始渲染, 導(dǎo)致性能問題,所以,在做性能優(yōu)化的同時,請求后端伙伴協(xié)助,也是性能優(yōu)化的一個方案

          排查性能瓶頸

          上述分析,根據(jù)三個指標(biāo)提供了一些常規(guī)的優(yōu)化手段,那么在這些優(yōu)化手段中,有的你可以立馬排查到,并且優(yōu)化例如:

          1. 優(yōu)化圖像,優(yōu)化字體大小
          2. 跟服務(wù)端配合利用瀏覽器緩存機制.啟用cdn、啟用gzip等
          3. 減少網(wǎng)絡(luò)協(xié)議過程中的消耗,減少http 請求、減少dns查詢、避免重定向
          4. 優(yōu)化關(guān)鍵渲染路徑,異步加載js等

          但是有的優(yōu)化手段我們不容易排查,因為他是打在包里面的,這個js 文件包含了很多邏輯怎么辦,這里我有兩個手段或許能夠幫助排查出性能瓶頸發(fā)生在哪里:

          分析包內(nèi)容

          在通常情況下,我們無法判斷的優(yōu)化點,都是在打包后,我們無法分析出,那些東西不是我們在首屏必須需要的,從而不能做出針對新的優(yōu)化,為了解決當(dāng)前問題,各大bundle廠商也都有各自的分析包的方案

          以vue-cli 為例

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

          我們只需要在腳手架中提供以上命令,就能在打包時生成,整個包的分析文件

          如上圖所示 在打包后就能分析出打包后的js 文件他包含什么組件,如此以來,我們就能知道那些文件是沒必要同步加載的,或者走cdn的,通過配置將他單獨的隔離開來,從而找出性能的問題

          利用chorme devtool 的代碼覆蓋率

          如下圖所示,

          利用 devtool的代碼覆蓋率檢查就能知道那些js 或者css 文件的代碼沒有被使用過,結(jié)合包內(nèi)容的分析,我們就能大概的猜出性能的瓶頸在哪里從而做相應(yīng)的特殊處理

          針對vue 的特殊優(yōu)化

          以上內(nèi)容都是通用的一些優(yōu)化手段,您在哪都能查到,只是我表達(dá)了一下做這些常規(guī)優(yōu)化的深層原因。能讓您更清楚的了解這些原因之后,在性能瓶頸的時候能游刃有余,而不是為了面試死記硬背,一到用的時候就不靈

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

          圖片懶加載

          所謂圖片懶加載,就是頁面只渲染當(dāng)前可視區(qū)域內(nèi)的圖片,如此一來,減少了其他圖片渲染數(shù)量,能大大提高SpeedIndexLCP的時間,從而提高分?jǐn)?shù)

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

          使用方式簡單,功能豐富

          虛擬滾動

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

          在vue中比較好用的插件有兩個vue-virtual-scroller[16]vue-virtual-scroll-list[17]

          目前我司統(tǒng)一用的vue-virtual-scroll-list 他下拉的時候到了分頁的地方能加些loading提示

          vue 中的函數(shù)式組件

          在vue中我們知道組件的初始化是比較損耗性能的,大家可以去試一下,使用vue 直接渲染一個文字內(nèi)容,和直接渲染一個app.vue 組件他的分?jǐn)?shù)是略有不同的。

          但是當(dāng)有了函數(shù)式組件,這個問題就迎刃而解了

          因為函數(shù)是組件顧名思義他就是個函數(shù),說白了就是個render函數(shù),他少了組件初始化的過程,省去了很多初始化過程的開銷

          什么時候用函數(shù)式組件呢?

          當(dāng)你的組件中沒有業(yè)務(wù)邏輯只展示內(nèi)容時,這時候函數(shù)式組件就派上用場了

          利用v-show 、KeepAlive 復(fù)用dom

          我們知道v-show是通過display 控制dom的展示隱藏,他并不會刪除dom 而我們在切換v-show的時候其實是減少了diff的對比,而KeepAlive 則是直接復(fù)用dom,連diff 的過程都沒了,并且他們倆的合理使用還不會影響到初始化渲染。如此一來減少了js 的執(zhí)行開銷,但是值得注意的是,他并不能優(yōu)化你初始化的性能,而是操作中的性能

          分批渲染組件

          在前面我們提到過SpeedIndex 的漸進(jìn)渲染是提高SpeedIndex的關(guān)鍵,有了這個前提,我們就可以分批異步渲染組件。先看到內(nèi)容,然后在渲染其他內(nèi)容

          舉個例子:

          <template>
              <div>
                  {{ data1 }}
              </div>

              <div v-if="data1">
                  {{ data2 }}
              </div>

          </template>
          <script>
          import { ref } from 'vue'
          export default {
              setup() {
                  let data1 = ref('')
                  let data2 = ref('')
                  /
          / 假設(shè) 這是從后端取到的數(shù)據(jù)
                  const data = {
                      data1: '這是渲染內(nèi)容1',
                      data2: '這是渲染內(nèi)容2'
                  }
                  data1.value = data.data1
                  /
          /利用requestAnimationFrame 在空閑的時候當(dāng)前渲染之后在渲染剩余內(nèi)容
                  requestIdleCallback(() => {
                      data2.value = data.data2
                  })
                  return {
                      data1,
                      data2
                  }
              },
          }
          </
          script>

          上述例子比較簡單可能描述的不太貼切,在這里特此說明一下,當(dāng)前方法適用于組件內(nèi)容較多,每次render 時間過長,導(dǎo)致白屏?xí)r間過長,比如,一次拉取用戶列表,那么分批渲染就非常合適,先展示一部分用戶信息,最后直到慢慢將所有內(nèi)容渲染完畢。如此對瀏覽器的SpeedIndex 也非常友好

          最后

          性能優(yōu)化一直是一個很火的話題, 不管從面試以及工作中都非常重要,有了這些優(yōu)化的點,你在寫代碼或者優(yōu)化老項目時都能游刃有余,能提前考慮到其中的一些坑,并且規(guī)避。

          但是大家需要明白的是,不要為了性能優(yōu)化而性能優(yōu)化,我們在要因地制宜,在不破壞項目可維護(hù)性的基礎(chǔ)上去優(yōu)化,千萬不要你優(yōu)化個項目性能是好了,但是大家都看不懂了,這就有點得不償失了,還是那句話,60分萬歲61份浪費,差不多得了,把經(jīng)歷留著去干更重要的事情!

          參考資料

          [1]

          lighthouse: https://link.zhihu.com/?target=https://github.com/GoogleChrome/lighthouse

          [2]

          首次內(nèi)容繪制: https://web.dev/i18n/zh/fcp/

          [3]

          可交互時間: https://web.dev/i18n/zh/tti/

          [4]

          速度指標(biāo): https://web.dev/speed-index/

          [5]

          總阻塞時間: https://web.dev/i18n/zh/tbt/

          [6]

          最大內(nèi)容繪制: https://web.dev/i18n/zh/lcp/

          [7]

          累積布局偏移: https://web.dev/i18n/zh/cls/

          [8]

          url(): https://developer.mozilla.org/docs/Web/CSS/url()

          [9]

          CSS 漸變: https://developer.mozilla.org/docs/Web/CSS/CSS_Images/Using_CSS_gradients

          [10]

          塊級元素: https://developer.mozilla.org/docs/Web/HTML/Block-level_elements

          [11]

          關(guān)鍵渲染路徑: https://developer.mozilla.org/zh-CN/docs/Web/Performance/Critical_rendering_path

          [12]

          PerformanceEntryhttps://developer.mozilla.org/docs/Web/API/PerformanceEntry

          [13]

          字體阻塞期:https://developer.mozilla.org/docs/Web/CSS/@font-face/font-disply#The_font_display_timeline

          [14]

          tinypng.com:https://tinypng.com/

          [15]

          vue-lazyload:https://github.com/hilongjw/vue-lazyload

          [16]

          vue-virtual-scroller:https://github.com/Akryum/vue-virtual-scroller

          [17]

          vue-virtual-scroll-list:https://github.com/tangbc/vue-virtual-scroll-list

          作者:好學(xué)習(xí)吧丶

          https://juejin.cn/post/7089241058508275725

          - EOF -

          瀏覽 22
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          評論
          圖片
          表情
          推薦
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  国产精品日韩欧美大师 | 日韩毛片在线免费观看 | 日韩视频二区在线 | 欧美日本中文字幕 | aaa在线免费观看 |