一次前端性能優(yōu)化——性能得分從56到96

作者:NewName

https://juejin.cn/post/7273072756156235834

最近看了一篇前端性能優(yōu)化的文章,之前也沒搞過性能優(yōu)化独郎,就學習了一下淹真。要想搞性能優(yōu)化吮成,得知道都有哪些和性能相關的指標,得知道有什么工具可以量化地評估網(wǎng)站的性能表現(xiàn)凭迹,還得知道怎么進行優(yōu)化婴削、優(yōu)化的思路都有啥。學了一波即碗,決定用Lighthouse這款性能測試工具來評估一下自己開發(fā)的網(wǎng)站的性能,優(yōu)化前得分56,優(yōu)化后得分96,怎么做的呢虫溜?閱讀本文一起學習吧~

image.png
image.png

1. Lighthouse的使用

Lighthouse 是由Google 開發(fā)并開源的Web 性能測試工具,通過監(jiān)控和檢測網(wǎng)站應用的各方面性能表現(xiàn)初橘,為開發(fā)這提供優(yōu)化用戶體驗和網(wǎng)站性能提供指導建議。

下面介紹兩種使用Lighthouse的方式:通過Chrome插件使用和通過Node CLI使用充岛。

1.1 通過Chrome插件使用

首先現(xiàn)在Lighthouse插件(Lighthouse谷歌瀏覽器插件下載地址:https://chrome.google.com/webstore/detail/lighthouse/blipmdconlkpinefehnmjammfjpmpbjk/related保檐。

然后打開Chrome開發(fā)者工具,點擊右上角的【三個點】崔梗,點擊【更多工具】夜只,再點擊【性能監(jiān)視器】:

image.png

然后點擊【Lighthouse】選項卡,點擊【分析網(wǎng)頁加載情況】按鈕:

image.png

如下為正在夾斷網(wǎng)頁得分:

image.png

幾秒后蒜魄,Lighthouse性能分析報錯生成:

image.png

可見性能分數(shù)比較低扔亥,具體指標得分如下:

image.png

點擊【展開視圖】可以了解每一指標的含義场躯,可以點擊連接了解每一指標的詳情以及具體優(yōu)化策略:

image.png

再往下可以查看優(yōu)化建議:

image.png

再往下可以看診斷結果:

image.png

1.2 通過Node CLI使用

目前Lighthouse已經(jīng)發(fā)布了npm包,可以在項目中集成:npm i lighthouse

如下為腳本代碼:

const run = async () => {
  const browser = await puppeteer.launch({
    headless: "new",
    args: ["--no-sandbox", "--disable-setuid-sandbox"],
  });
  const page = await browser.newPage();
  const url = "你的網(wǎng)頁url";
  await page.goto(url);
  const { port } = new URL(browser.wsEndpoint());
  const { report } = await lighthouse(url, {
    port,
    output: "html",
  });
  await writeFile("report.html", report);
  await browser.close();
};
run();

運行腳本即可得到Lighthouse生成的分析報告:

image.png

分析報告和瀏覽器插件方式得到在內(nèi)容上是的一樣旅挤,只不過是英文的形式踢关。后續(xù)可以利用在此基礎上進行改善和豐富,可以優(yōu)化前端工程的部署流程谦铃。

有了性能分析報告耘成,我們可以根據(jù)各性能指標得分,優(yōu)化建議和診斷結果對項目進行優(yōu)化驹闰,下面具體學習一下這些性能優(yōu)化指標。

2. 性能優(yōu)化的指標

2.1 FCP ( First Contentful Paint)首次內(nèi)容繪制

image.png

2.1.1 定義

首次內(nèi)容繪制時間撒会,測量頁面從開始加載到頁面內(nèi)容的任何部分在屏幕上完成渲染的時間嘹朗。

2.1.2 對定義的理解

所述頁面內(nèi)容必須是文本、圖片(包含背景圖)诵肛,非白色的canvas或SVG屹培。

這是用戶第一次看到頁面的內(nèi)容,注意是部分內(nèi)容怔檩,并非所有內(nèi)容褪秀。

如下圖所示,F(xiàn)CP 發(fā)生在第二幀薛训,因為那是首批文本和圖像元素在屏幕上完成渲染的時間點:

image.png

如上圖所示媒吗,雖然部分內(nèi)容已完成渲染,但并非所有內(nèi)容都已經(jīng)完成渲染乙埃。這是首次內(nèi)容繪制時間 (FCP) 與*最大內(nèi)容繪制時間 (LCP闸英,Largest Contentful Paint)之間的重要區(qū)別。

2.1.3 評價標準

image.png

FCP時間在0-1.8秒介袜, 表示良好甫何,顏色為綠色,F(xiàn)CP評分將在75~100分遇伞;

FCP時間在1.9-3.0秒辙喂, 表示需要改進,顏色為橙色鸠珠,F(xiàn)CP評分將在50~74分巍耗;

FCP時間在3.1秒以上, 表示較差進跳芳,顏色為紅色芍锦,F(xiàn)CP評分將在0~49分。

2.1.4 縮短FCP時間的方法

指導方案可參照:如何改進 FCP [1]飞盆,本文如何做的見下文娄琉。

2.1.5 注意事項

此指標對于沒有使用ssr技術的web項目意義并不大次乓,因為第一繪制發(fā)生的時間通常JS還沒加載完畢。

2.2 LCP(Largest Contentful Pain)最大內(nèi)容繪制

image.png

2.2.1 定義

最大內(nèi)容繪制時間孽水,根據(jù)頁面首次開始加載的時間點來計算可視區(qū)域內(nèi)可見的最大圖像或者文本塊完成渲染的相對時間票腰。

2.2.2 對定義的理解

LCP要考慮的元素包括:img元素以及內(nèi)嵌在svg元素內(nèi)的img元素,video元素女气,通過url()加載的背景圖像元素杏慰,包含文本節(jié)點或者其他內(nèi)聯(lián)級文本元素的塊級元素。

如下圖所示炼鞠,最大元素隨內(nèi)容加載而變化缘滥,隨著新內(nèi)容被添加進 DOM,并因此使最大元素發(fā)生了改變:

image.png

2.2.3 評價標準

image.png

LCP時間在0-2.5秒谒主, 表示良好朝扼,顏色為綠色;

LCP時間在2.6-4.0秒霎肯, 表示需要改進擎颖,顏色為橙色;

LCP時間在4.1秒以上观游, 表示較差進搂捧,顏色為紅色。

2.2.4 縮短LCP時間的方法

指導方案可參考:如何改進 LCP[2]懂缕,本文如何做的見下文允跑。

2.2.5 注意事項

在某些情況下,頁面上最重要的元素(或多個元素)并不是最大元素提佣,而開發(fā)者可能更有興趣測量前者的渲染時間(使用元素計時API[3])吮蛹。

2.3 TBT (Total Blocking Time)總阻塞時間

2.3.1 定義

總阻塞時間 (TBT) 指標測量First Contentful Paint 首次內(nèi)容繪制 (FCP)與Time to Interactive 可交互時間 (TTI)之間的總時間。

2.3.2 對定義的理解

由定義可知:TBT涉及到了FCP和TTI這兩個概念拌屏, 對于FCP上文已經(jīng)介紹過潮针,這里補充一下TTI(可交互時間的定義):TTI 指標測量頁面從開始加載到主要子資源完成渲染,并能夠快速倚喂、可靠地響應用戶輸入所需的時間每篷。

2.3.3 評價標準

評價標準參加下表:

image.png

TBT得分標準[4]

為了提供良好的用戶體驗,網(wǎng)站在普通移動硬件上進行測試時端圈,應當努力使TBT控制在300毫秒以內(nèi)焦读。

2.3.4 縮短TBT的方法

指導方案可參考:如何改進TBT[5],本文如何做的見下文舱权。

2.4 CLS(Cumulative Layout Shift)累積布局偏移

image.png

2.4.1 定義

CLS 測量整個頁面生命周期內(nèi)發(fā)生的所有意外布局偏移中最大一連串的布局偏移分數(shù)矗晃。

2.4.2 對定義的理解

累積布局偏移 (CLS) 是測量視覺穩(wěn)定性的一個以用戶為中心的重要指標,因為該項指標有助于量化用戶經(jīng)歷意外布局偏移的頻率宴倍,較低的 CLS 有助于確保一個頁面是令人愉悅的张症。

2.4.3 評價標準

image.png

2.4.4 縮短CLS的方法

指導方案可參照:如何改進CLS[6]仓技,本文不涉及。

2.5 SI(Speed Index)速度指標

2.5.1 定義

SI是一個表示頁面可視區(qū)域中內(nèi)容的填充速度的指標俗他。

2.5.2 對定義的理解

該指標捕獲的是頁面出現(xiàn)像素點的時間脖捻。

2.5.3 評價標準

評價標準參加下表:

image.png

2.5.5 縮短SI的方法

指導方案可參照:如何改進SI[7],本文如何做的見下文兆衅。

3. 具體的性能優(yōu)化的方法

文檔快速加載總結了一些提升網(wǎng)站性能的技術地沮,列出一下常用的方法:

1.消除阻塞渲染的資源: 例如對于引入三方的script標簽加上async或者defer。

2.縮小CSS羡亩、移除未使用的CSS: 例如使用壓縮器壓縮CSS摩疑。

3.預連接到所需要的資源:例如使用<link rel="preconnect">通知瀏覽器,頁面打算與另一個源建立連接夕春,而且希望該過程盡快開始未荒。

4.減少服務器的響應時間:例如使用HTTP2。

5.使用緩存:例如使用HTTP緩存及志。

6.優(yōu)化圖片:例如壓縮圖片,使用CDN, 延遲加載等寨腔。

7.刪除未使用代碼:例如刪除未使用的庫速侈,刪除不需要的庫,刪除無用代碼迫卢,按需引入組件庫倚搬。

8.減少JS負載:例如動態(tài)導入和代碼拆分。

下面結合筆者的項目介紹一下筆者使用的方法:

3.1 使用vite-compression-plugin

可以使用 vite-compression-plugin[8] 來對代碼進行gizp壓縮乾蛤,使用方法如下:

vite.config.ts:

import viteCompression from 'vite-plugin-compression'
export default defineConfig({
  plugins:[
    viteCompression({
      ext: ".gz",
      algorithm: "gzip",
      deleteOriginFile: false
    })
  ]
})

關于插件的具體配置可以查看插件的文檔每界,選擇合適的壓縮算法。

3.2 開啟ngnix的gizp壓縮

筆者的前端項目下有一個.devops目錄家卖,下面有一個ngnix.conf文件可以單獨配置此前端工程的ngnix:

image.png

配置方法為在server下面增加如下配置:

server {
  gzip on;
  gzip_buffers 32 4K;
  gzip_comp_level 6;
  gzip_min_length 100;
  gzip_types application/javascript text/plain text/css text/xml application/json application/xml application/xml+rss;
  gzip_vary on;
  listen       80;
  location / {            
    # 此處省略location相關配置
  }
}

具體配置項含義以及取值眨层,可以查詢相關文檔。

3.3 按需自動引入element-plus

筆者項目原來是完整引入element-plus的, main.ts文件內(nèi)容:

import ElementPlus from 'element-plus'
import 'element-plus/dist/index.css'
import App from './App.vue'

const app = createApp(App)

app.use(ElementPlus)
app.mount('#app')

這樣會導致首頁加載時被打包后的和element-plus相關的全部js和css資源被引入上荡,但是按需引入時則不會一次性引入全部的css和js趴樱。

按需引入element-plus的方法為:

第一步:安裝unplugin-auto-import和unplugin-vue-components:pnpm install unplugin-auto-import unplugin-vue-components。

第二步:vite.config.ts插件配置:

import AutoImport from "unplugin-auto-import/vite";
import Components from "unplugin-vue-components/vite";
import { ElementPlusResolver } from "unplugin-vue-components/resolvers";
export default defineConfig({
  plugins:[
    AutoImport({
      resolvers: [ElementPlusResolver()]
    }),
    Components({
      resolvers: [ElementPlusResolver()]
    }),
  ]
})

第三步:特殊插件的處理酪捡。對于對于命令式方式使用的組件叁征,例如ElNotification, 如果不單獨引入,則會導致其樣式失效逛薇,所以需要對項目中使用到的這類組件單獨全局引入一下就OK啦:

import { ElInput, ElSelect, ElDatePicker, ElTimePicker } from "element-plus";
app.use(ElInput).use(ElSelect).use(ElDatePicker).use(ElTimePicker).use(directives).use(router).use(pinia).mount("#app");

3.4 修改百度地圖的引入方式

原來的引入方式是在html文件中增加script標簽:

<!DOCTYPE html>
<html lang="en">
  <body >
    <div id="app">
    <script type="module" src="/src/main.ts"></script>
    <script charset="utf-8" src="https://api.map.baidu.com/api?v=1.0&&type=webgl&ak=***"></script>
  </body>
</html>

原來的使用方法如下:

const BMapGL: any = (window as any).BMapGL;
 const map = new BMapGL.Map("container");

改成使用時異步引用:

const LoadBaiduMapScript = () => {
  //console.log("初始化百度地圖腳本...");
  const AK = "***";
  const BMap_URL = "https://api.map.baidu.com/api?v=1.0&&type=webgl&ak=" + AK + "&s=1&callback=onBMapCallback";
  return new Promise(resolve => {
    // 如果已加載直接返回
    if (typeof (window as any).BMapGL !== "undefined") {
      resolve((window as any).BMapGL);
      return true;
    }
    // 百度地圖異步加載回調(diào)處理
    (window as any).onBMapCallback =  () => {
      console.log("百度地圖腳本初始化成功...");
      BMapGL = (window as any).BMapGL;
      resolve((window as any).BMapGL);
    };
    // 插入script腳本
    let scriptNode = document.createElement("script");
    scriptNode.setAttribute("type", "text/javascript");
    scriptNode.setAttribute("src", BMap_URL);
    document.body.appendChild(scriptNode);
  });
};

3.5 對圖片進行壓縮

這里推薦一個好用的壓縮工具捺疼,熊貓壓縮——tinypng 。

image.png

用它把UI給的切圖永罚、背景圖等壓縮一下啤呼,那必然也起到一定的作用卧秘。

筆者就通過如上五種優(yōu)化方法對項目優(yōu)化了一下,性能得分就得到了很大的改觀媳友,是不是覺得性能優(yōu)化也不難斯议,哈哈哈~

參考資料

[1]如何改進 FCP : https://web.dev/fcp/#
%E5%A6%82%E4%BD%95%E6%94%B9%E8%BF%9B-fcp

[2]如何改進 LCP: https://web.dev/lcp/#
%E5%A6%82%E4%BD%95%E6%94%B9%E8%BF%9B-lcp

[3]使用元素計時API:
https://wicg.github.io/element-timing/

[4]TBT得分標準:
https://developer.chrome.com/docs/lighthouse/performance/lighthouse-total-blocking-time/#how-lighthouse-determines-your-tbt-score

[5]如何改進TBT: https://web.dev/tbt/#
%E5%A6%82%E4%BD%95%E6%94%B9%E8%BF%9B-tbt

[6]如何改進CLS: https://web.dev/cls/#
%E5%A6%82%E4%BD%95%E6%94%B9%E8%BF%9B-cls

[7]如何改進SI:
https://developer.chrome.com/docs/lighthouse/performance/speed-index/#how-to-improve-your-speed-index-score

[8]vite-compression-plugin: https://github.com/nonzzz/vite-plugin-compression

?著作權歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市醇锚,隨后出現(xiàn)的幾起案子哼御,更是在濱河造成了極大的恐慌,老刑警劉巖焊唬,帶你破解...
    沈念sama閱讀 221,576評論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件恋昼,死亡現(xiàn)場離奇詭異,居然都是意外死亡赶促,警方通過查閱死者的電腦和手機液肌,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,515評論 3 399
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來鸥滨,“玉大人嗦哆,你說我怎么就攤上這事⌒鲎遥” “怎么了老速?”我有些...
    開封第一講書人閱讀 168,017評論 0 360
  • 文/不壞的土叔 我叫張陵,是天一觀的道長凸主。 經(jīng)常有香客問我橘券,道長,這世上最難降的妖魔是什么卿吐? 我笑而不...
    開封第一講書人閱讀 59,626評論 1 296
  • 正文 為了忘掉前任旁舰,我火速辦了婚禮,結果婚禮上嗡官,老公的妹妹穿的比我還像新娘箭窜。我一直安慰自己,他們只是感情好谨湘,可當我...
    茶點故事閱讀 68,625評論 6 397
  • 文/花漫 我一把揭開白布绽快。 她就那樣靜靜地躺著,像睡著了一般紧阔。 火紅的嫁衣襯著肌膚如雪坊罢。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 52,255評論 1 308
  • 那天擅耽,我揣著相機與錄音活孩,去河邊找鬼。 笑死乖仇,一個胖子當著我的面吹牛憾儒,可吹牛的內(nèi)容都是我干的询兴。 我是一名探鬼主播,決...
    沈念sama閱讀 40,825評論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼起趾,長吁一口氣:“原來是場噩夢啊……” “哼诗舰!你這毒婦竟也來了?” 一聲冷哼從身側響起训裆,我...
    開封第一講書人閱讀 39,729評論 0 276
  • 序言:老撾萬榮一對情侶失蹤眶根,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后边琉,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體属百,經(jīng)...
    沈念sama閱讀 46,271評論 1 320
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 38,363評論 3 340
  • 正文 我和宋清朗相戀三年变姨,在試婚紗的時候發(fā)現(xiàn)自己被綠了族扰。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 40,498評論 1 352
  • 序言:一個原本活蹦亂跳的男人離奇死亡定欧,死狀恐怖渔呵,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情砍鸠,我是刑警寧澤厘肮,帶...
    沈念sama閱讀 36,183評論 5 350
  • 正文 年R本政府宣布,位于F島的核電站睦番,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏耍属。R本人自食惡果不足惜托嚣,卻給世界環(huán)境...
    茶點故事閱讀 41,867評論 3 333
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望厚骗。 院中可真熱鬧示启,春花似錦、人聲如沸领舰。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,338評論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽冲秽。三九已至舍咖,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間锉桑,已是汗流浹背排霉。 一陣腳步聲響...
    開封第一講書人閱讀 33,458評論 1 272
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留民轴,地道東北人攻柠。 一個月前我還...
    沈念sama閱讀 48,906評論 3 376
  • 正文 我出身青樓球订,卻偏偏與公主長得像,于是被迫代替她去往敵國和親瑰钮。 傳聞我的和親對象是個殘疾皇子冒滩,可洞房花燭夜當晚...
    茶點故事閱讀 45,507評論 2 359

推薦閱讀更多精彩內(nèi)容