Vue的性能優(yōu)化

定位應(yīng)用的性能問題

Vue應(yīng)用的性能問題可以分為兩個部分:運(yùn)行時性能問題暇韧,加載性能問題新博。
和其他 web應(yīng)用一樣,定位 Vue應(yīng)用性能問題最好的工具是 Chrome Devtool(F12 谷歌開發(fā)者工具),通過 Performance 工具可以用來錄制一段時間的 CPU 占用业簿、內(nèi)存占用、FPS 等運(yùn)行時性能問題阳懂,通過 Network 工具可以用來分析加載性能問題梅尤。

Chrome Performance 常見的名詞指標(biāo)

Performance.png
  • FP:First Paint 首次繪制柜思,第一幀數(shù)據(jù)渲染出來時
    標(biāo)記瀏覽器渲染任何在視覺上不同于導(dǎo)航前的屏幕內(nèi)容的時間點(diǎn)

  • FCP:First Contentful Paint 首次內(nèi)容繪制
    標(biāo)記瀏覽器渲染來自DOM第一位內(nèi)容的時間點(diǎn),該內(nèi)容可能是文本巷燥、圖像赡盘、SVG,元素

  • LCP:Largest Contentful Paint 最大內(nèi)容渲染缰揪,2019.11新增
    代表在viewport中最大的頁面元素加載的事件陨享。LCP的數(shù)據(jù)會通過PerformanceEntry對象記錄,每次出現(xiàn)更大的內(nèi)容渲染 則會產(chǎn)生一個新的PerformanceEntry對象

  • DCL:DomContentLoaded
    當(dāng)HTML文檔被完全加載和解析完成之后钝腺,DomContentLoaded事件被觸發(fā)抛姑,無需等待樣式表、圖像和子框架的完成加載艳狐。

  • FMP:First Meaningful Paint 首次有效繪制
    主內(nèi)容的繪制定硝,視頻網(wǎng)站的主角元素自然是視頻,微博網(wǎng)站的博文是主要元素

  • L:onLoad
    當(dāng)依賴的資源全部加載完成后才會觸發(fā)

  • TTI:Time to Interactive 可交互時間
    用于標(biāo)記程序已進(jìn)行視覺渲染并能可靠響應(yīng)用戶輸入的時間點(diǎn)

  • TBT:Total Blocking Time 頁面阻塞總時長
    匯總所有加載過程中阻塞用戶操作的時長毫目,在FCPTTI之間任何long task(執(zhí)行時間超過一定閾值蔬啡,如50ms)中阻塞部分都會被匯總

  • FID:First Input Delay 首次輸入延遲
    衡量從用戶首次與網(wǎng)站交互 到 瀏覽器實(shí)際能夠訪問 之間的時間

  • SI:Speed Index
    用于顯示頁面可見部分的顯示速度(時間)

我們通常要關(guān)心指標(biāo):FP、FCP镀虐、FMP

首頁白屏優(yōu)化

對于打包后的SPA程序箱蟆,index.html是一個空的,所以首次渲染的頁面也是空的(FP)刮便,也就是白屏狀態(tài)空猜;
等待JS加載完成,異步請求數(shù)據(jù)诺核,在未來的某一幀才開始渲染出大體內(nèi)容架構(gòu)(FCP)抄肖,但仍缺少一些圖片等資源,且無法交互窖杀;
從而可知漓摩,為了減少白屏?xí)r間,可以把 FCP 階段提前:

  • 骨架屏策略:在上線之前入客,通過JS或框架在index.html中插入大體的頁面結(jié)構(gòu)管毙;
  • 預(yù)渲染:靜態(tài)渲染,對于不變的內(nèi)容在本地預(yù)渲染桌硫,而變化的內(nèi)容預(yù)留占位夭咬。

資源優(yōu)化

prefetch

prefetch 預(yù)獲取,分為三種類型:link prefetch铆隘、dns prefetch卓舵、prerender

  1. link prefetch
    在瀏覽器空閑時加載一個資源(HTML、JS膀钠、CSS掏湾、Image裹虫、Font),是真正的資源下載融击;
        <link ref="prefetch" >  //谷歌
        <link ref="prefetch" href="/uploads/images/bg.png">
    
    注意:雖然預(yù)獲取了筑公,但頁面不會解析,JS不會被執(zhí)行尊浪。
  2. dns prefetch
    前端優(yōu)化與DNS相關(guān)的有兩點(diǎn):減少DNS的請求次數(shù)匣屡,DNS預(yù)解析
        <!-- 開啟DNS預(yù)獲取,好像也不需要 -->
        <meta http-equiv="x-dns-prefetch-control" content="on">
        <!-- 設(shè)置DNS預(yù)解析的域名 -->
        <link rel="dns-prefetch"  />
    
    提前解析當(dāng)前頁面中與當(dāng)前域名不在同一個域的域名(第三方域名)拇涤,并緩存結(jié)果捣作,但不會下載任何資源,所以寫入具體的JS工育、Image等資源沒有意義虾宇。
    當(dāng)用戶真正點(diǎn)擊網(wǎng)頁上的域名鏈接時,DNS早已在后臺解析完成如绸,所以能減少等待時間,提升用戶體驗(yàn)旭贬。
  3. prerender 預(yù)渲染
    不僅會加載資源怔接,還會解析并預(yù)渲染頁面。但是否執(zhí)行預(yù)渲染是根據(jù)瀏覽器自身判斷的稀轨,瀏覽器可能會:
    • 分配少量資源對頁面進(jìn)行預(yù)渲染扼脐;
    • 掛起部分請求直至頁面可見時;
    • 可能放棄預(yù)渲染奋刽,如果消耗資源過多等等情況瓦侮。。佣谐。
        <link rel="prerender"  />
    
    很顯然肚吏,它是一個相對非常“重”的操作(資源浪費(fèi)嚴(yán)重)狭魂,瀏覽器會提前加載所有資源罚攀,并把渲染結(jié)果緩存在內(nèi)存中。
    SPA項(xiàng)目中基本沒有應(yīng)用場景雌澄,對于MPA項(xiàng)目斋泄,在確定用戶一定會進(jìn)入該頁面的情況下,可以考慮使用prerender镐牺。

preconnect

preconnect 預(yù)連接

    <!-- 谷歌使用了預(yù)鏈接 -->
    <link ref="preconnect" >

瀏覽器要建立一個連接炫掐,需要經(jīng)過DNS解析,TCP三次握手和TLS協(xié)商(https)睬涧,這些過程也相當(dāng)?shù)暮臅r募胃。dns-prefetch只是做了DNS解析旗唁,而preconnect把這三步都做了,使瀏覽器預(yù)先建立一個連接摔认,等真正需要加載資源時能直接請求逆皮。

preload

preload 預(yù)加載,它的作用是將資源率先加載参袱,聽起來容易和prefetch混淆:

  • prefetch 是預(yù)獲取电谣,是對用戶接下來很可能會使用到的資源的預(yù)先下載;
  • preload 本質(zhì)上是影響資源的加載順序抹蚀,把可能后置下載的資源前置下載剿牺。

preload的特點(diǎn)

  • 具有優(yōu)先級,但不會阻塞onload事件:preload在網(wǎng)頁中具有強(qiáng)制加載的功能环壤,所以它的加載具有優(yōu)先級晒来,不過它僅僅是加載資源,并不會執(zhí)行郑现,所以仍需要 script 加載資源;
  • 它設(shè)計(jì)的目的是為當(dāng)前頁面的資源進(jìn)行預(yù)加載湃崩,跳轉(zhuǎn)頁面后就使用不到了;
  • 使用as字段來設(shè)定優(yōu)先級,as=style 則為最高優(yōu)先級接箫。優(yōu)先級順序?yàn)椋?code>HTML/CSS>Images>JS

舉個栗子
當(dāng)資源沒有直接體現(xiàn)在HTML中攒读,而是隱藏在CSSJS里,preload可以提前告知瀏覽器隱藏資源的存在辛友,以便瀏覽器做出最優(yōu)的安排薄扁。

# style.css
    @font-face {
        font-family: myFirstFont;
        src: url('https://fonts.gstatic.com/s/sofia/v8/8QIHdirahM3j_su5uI0Orbjl.woff2');
    }
    h1 {
        font-family: myFirstFont;
    }
  • 未配置preload
    <head>
        <link rel="stylesheet" href="style.css">
    </head>
    
    加載過程
no preload.png

對字體的下載發(fā)生在CSS下載之后,因?yàn)橹挥挟?dāng)瀏覽器下載完CSS并解析之后废累,才知道字體資源的存在邓梅;

  • 配置上 preload
    <link rel="preload" 
        
       as="font" crossorigin="anonymous">
    <link rel="stylesheet" href="style.css">
    
    加載過程
with preload.png

同時下載字體和CSS,因?yàn)闉g覽器提前知道了隱藏資源的存在邑滨,做出了最優(yōu)安排日缨。與未配置preload相比,下載時間減少了驼修。

小結(jié)

  • 如果出現(xiàn)跨域無法加載殿遂,則加上 crossorigin 字段;
  • 這些優(yōu)化都是屬于勤快優(yōu)化類型乙各,將數(shù)據(jù)的加載和數(shù)據(jù)的使用/解析分開墨礁,且都有完整的工程化打包方案,如webpack耳峦,很多大站都會使用這些優(yōu)化方式恩静。

優(yōu)化無限列表性能

如果應(yīng)用中存在非常長或者無限滾動的列表,那么采用 窗口化 的技術(shù)來優(yōu)化性能,只需要渲染少部分區(qū)域的內(nèi)容驶乾,減少重新渲染組件和創(chuàng)建 DOM 節(jié)點(diǎn)的時間邑飒。
vue-virtual-scroll-listvue-virtual-scroller 都是解決這類問題的開源項(xiàng)目。還可以參考 Google工程師的文章Complexities of an Infinite Scroller來嘗試自己實(shí)現(xiàn)一個虛擬的滾動列表來優(yōu)化性能级乐,主要使用到的技術(shù)是 DOM 回收疙咸、墓碑元素滾動錨定

組件懶加載

上面提到的無限列表的場景风科,比較適合列表內(nèi)元素非常相似的情況撒轮。不過有時候,你的Vue應(yīng)用的超長列表中的內(nèi)容往往不盡相同贼穆,例如在一個復(fù)雜應(yīng)用的主界面中题山,由非常多不同的模塊組成,而用戶看到的往往只有首屏一兩個模塊故痊。但在初始渲染時顶瞳,不可見區(qū)域的模塊也會執(zhí)行和渲染,從而帶來一些額外的性能開銷愕秫。
使用組件懶加載在不可見時只需要渲染一個骨架屏慨菱,不需要真正渲染組件。

懶加載也叫延遲加載戴甩,即在需要的時候進(jìn)行加載抡柿,隨用隨載;

  1. 實(shí)現(xiàn)思路:

    • 組件化
      將各模塊拆分為組件粒度等恐,降低耦合度;將組件依賴的資源(比如請求接口备蚓、請求相關(guān)的依賴資源)全部封裝在組件內(nèi)部進(jìn)行調(diào)用课蔬;
    • 加載優(yōu)先級
      優(yōu)先加載首屏可見模塊,其余不可見模塊懶加載郊尝,待可見或即將可見時加載二跋;
  2. 判斷可見性問題
    通過監(jiān)聽scrollresize事件來判斷模塊是否可見流昏,代碼不僅繁瑣扎即,而且一不小心沒有函數(shù)去抖就又可能導(dǎo)致嚴(yán)重的性能問題。
    H5新增的IntersectionObserver API是一個不錯的解決方案况凉,其設(shè)計(jì)是異步的谚鄙,回調(diào)是在主線程空閑時才執(zhí)行,而且保證回調(diào)執(zhí)行次數(shù)非常有限刁绒,在性能方面表現(xiàn)更優(yōu)闷营,使用起來也更簡單。
    當(dāng)然,低版本瀏覽器還是要通過 polyfill 兼容傻盟。

  3. 盡可能懶的條件渲染
    解決了可見性問題速蕊,懶加載就比較簡單了,Vue提供的 v-if 可以做到惰性渲染娘赴。

  4. 如果可見后進(jìn)行初始渲染规哲,可見前如何顯示
    如果在判斷加載條件為 false 時,什么都不渲染诽表,就會帶來一系列問題:

    • 用戶體驗(yàn)比較差唉锌,最開始是白屏,然后突然又渲染出現(xiàn)內(nèi)容关顷;
    • 最致命的是糊秆,判斷可見性需要一個目標(biāo)來觀察,如果什么不都渲染议双,那就無從觀察痘番。

    因此,引入一個骨架屏的概念平痰,為真實(shí)的組件創(chuàng)建一個在尺寸汞舱、樣式上非常接近真實(shí)組件的組件。
    骨架屏的作用:

    • 提升用戶感知體驗(yàn)宗雇;
    • 保證切換的一致性昂芜;
    • 提供可見性觀察的目標(biāo)對象。
骨架屏
  1. 如何提升切換時的體驗(yàn)
    在真實(shí)組件開始渲染時赔蒲,需要一定的時間和空間泌神,時間指的是真實(shí)組件從創(chuàng)建到渲染的時間,包括請求接口舞虱、請求資源和渲染的時間欢际,空間指的是頁面布局中需要給真實(shí)組件留出剛好的位置,避免產(chǎn)生抖動矾兜。
    我們可以使用Vue內(nèi)置的transition組件自定義骨架組件和真實(shí)組件的進(jìn)入和離開效果损趋,通過合理的布局和定位,減少切換時的抖動椅寺,通過設(shè)置過渡效果給真實(shí)組件留出一定的加載時間浑槽。

  2. Vue組件懶加載方案 --- Vue Lazy Component
    該插件支持 組件可見或即將可見時懶加載,支持 組件延時加載返帕,支持 加載組件前展示組件骨架桐玻,提高用戶體驗(yàn),支持 懶加載組件分包異步加載溉旋。

API上的優(yōu)化

  1. Object.freeze
    Object.freeze():把不會修改的對象/數(shù)組冷凍起來畸冲,Vue將不會對這些數(shù)據(jù)做響應(yīng)式處理。當(dāng)然,擅自修改這些數(shù)據(jù)也將會報錯給你看邑闲。
    const columnList = Object.freeze([
        { title: '姓名', key: 'name', align: 'center' },
        { title: '性別', key: 'gender', align: 'center' }
    ])
    
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末算行,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子苫耸,更是在濱河造成了極大的恐慌州邢,老刑警劉巖,帶你破解...
    沈念sama閱讀 206,723評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件褪子,死亡現(xiàn)場離奇詭異量淌,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)嫌褪,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,485評論 2 382
  • 文/潘曉璐 我一進(jìn)店門呀枢,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人笼痛,你說我怎么就攤上這事裙秋。” “怎么了缨伊?”我有些...
    開封第一講書人閱讀 152,998評論 0 344
  • 文/不壞的土叔 我叫張陵摘刑,是天一觀的道長。 經(jīng)常有香客問我刻坊,道長枷恕,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 55,323評論 1 279
  • 正文 為了忘掉前任谭胚,我火速辦了婚禮徐块,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘灾而。我一直安慰自己蛹锰,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,355評論 5 374
  • 文/花漫 我一把揭開白布绰疤。 她就那樣靜靜地躺著,像睡著了一般舞终。 火紅的嫁衣襯著肌膚如雪轻庆。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,079評論 1 285
  • 那天敛劝,我揣著相機(jī)與錄音余爆,去河邊找鬼。 笑死夸盟,一個胖子當(dāng)著我的面吹牛蛾方,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 38,389評論 3 400
  • 文/蒼蘭香墨 我猛地睜開眼桩砰,長吁一口氣:“原來是場噩夢啊……” “哼拓春!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起亚隅,我...
    開封第一講書人閱讀 37,019評論 0 259
  • 序言:老撾萬榮一對情侶失蹤硼莽,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后煮纵,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體懂鸵,經(jīng)...
    沈念sama閱讀 43,519評論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 35,971評論 2 325
  • 正文 我和宋清朗相戀三年行疏,在試婚紗的時候發(fā)現(xiàn)自己被綠了匆光。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,100評論 1 333
  • 序言:一個原本活蹦亂跳的男人離奇死亡酿联,死狀恐怖终息,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情货葬,我是刑警寧澤采幌,帶...
    沈念sama閱讀 33,738評論 4 324
  • 正文 年R本政府宣布,位于F島的核電站震桶,受9級特大地震影響休傍,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜蹲姐,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,293評論 3 307
  • 文/蒙蒙 一磨取、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧柴墩,春花似錦忙厌、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,289評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至歼指,卻和暖如春爹土,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背踩身。 一陣腳步聲響...
    開封第一講書人閱讀 31,517評論 1 262
  • 我被黑心中介騙來泰國打工胀茵, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人挟阻。 一個月前我還...
    沈念sama閱讀 45,547評論 2 354
  • 正文 我出身青樓琼娘,卻偏偏與公主長得像峭弟,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子脱拼,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,834評論 2 345