當我們疲於開發一個接一個的需求時,很容易忘記去關註網站的性能,到了某一個節點,猛地發現,隨著越來越多代碼的堆積,網站變得越來越慢。本文就是從這樣的一個背景出發,著手優化網站的前端性能,並總結出一套開發習慣,讓我們在日常開發時,也保持高性能,而不是又一次回過頭來優化性能。 ...
一、背景
當我們疲於開發一個接一個的需求時,很容易忘記去關註網站的性能,到了某一個節點,猛地發現,隨著越來越多代碼的堆積,網站變得越來越慢。
本文就是從這樣的一個背景出發,著手優化網站的前端性能,並總結出一套開發習慣,讓我們在日常開發時,也保持高性能,而不是又一次回過頭來優化性能。
指標名稱 | 優化前 | 優化後 | 提升 |
---|---|---|---|
Lighthouse Performance 評分 | 29 | 81 | 279% |
FCP(First Contentful Paint 首次內容繪製) | 0.7s | 0.7s | |
LCP(Largest Contentful Paint 最大內容繪製) | 6.2s | 2.5s | 248% |
TTI(Time to Interactive 可交互時間) | 10.1s | 2.1s | 480% |
Speed Index(速度指數) | 5.6s | 1.8 | 311% |
TBT(Total Blocking Time 總阻塞時間) | 820ms | 120ms | 683% |
優化前後對比:
二、優化前
接下來就是介紹下優化前我們要做哪些事件:
-
瞭解性能指標及測量工具
-
分析需要優化的地方
1. 瞭解測量工具及性能指標
一開始我們只是感受到網站的頁面打開時白屏時間較長,感覺性能是比較差的,那麼具體有哪些性能指標需要去關註呢?
這裡我使用的是 Chrome devtools 內置的Lighthouse,Lighthouse 是一種開源的自動化工具,用於提高 Web 應用程式的質量。
Lighthouse 會在一系列的測試下運行網頁,比如不同尺寸的設備和不同的網路速度。它還會檢查頁面對輔助功能指南的一致性,例如顏色對比度和 ARIA 最佳實踐。
打開 Chrome devtools Lighthouse 即可使用。
在比較短的時間內,Lighthouse 可以給出這樣一份報告。
這份報告從 5 個方面來分析頁面: 性能、輔助功能、最佳實踐、搜索引擎優化和 PWA。像性能方面,會給出一些常見的耗時統計。
1.1 Performance
Performance 評分統計,包括了以下指標:
1.1.1 FCP
FCP 測量在用戶導航到頁面後瀏覽器呈現第一段 DOM 內容所花費的時間。頁面上的圖像、非白色<canvas>
元素和 SVG 被視為 DOM 內容;不包括 iframe 內的任何內容。
1.1.2 LCP
LCP 測量視口中最大的內容元素何時呈現到屏幕上。這近似於頁面的主要內容對用戶可見的時間。
需要註意的是 LCP 的計算是一個動態的過程,如下圖最後的圖片才是這個頁面中的最大內容繪製的元素。
1.1.3 TTI
TTI 測量頁面完全交互所需的時間。
TTI 是如何計算的呢,如下圖首先延時間軸正向搜索時長至少為 5 秒的安靜視窗(安靜視窗是指沒有長任務且不超過兩個正在處理的網路 get 請求),然後沿時間軸反向搜索安靜視窗之前的最後一個長任務,如果沒有找到長任務,則在 FCP 步驟停止執行,TTI 就是安靜視窗之前最後一個長任務的結束時間,如果沒有找到長任務的話,則與 FCP 值相同。
1.1.4 Speed Index
Speed Index 衡量頁面載入期間內容以視覺方式顯示的速度。Lighthouse 首先捕獲瀏覽器中頁面載入的視頻,並計算幀之間的視覺進度。
1.1.5 TBT
TBT 測量頁面被阻止響應用戶輸入(例如滑鼠點擊、屏幕點擊或鍵盤按下)的總時間。
通過添加 First Contentful Paint 和 Time to Interactive 之間所有長任務的阻塞部分來計算總和。任何執行時間超過 50 毫秒的任務都是長任務。
50 毫秒後的時間量是阻塞部分。例如,如果 Lighthouse 檢測到一個 70 毫秒長的任務,則阻塞部分將為 20 毫秒。
如下圖淡紅色區域的時間總和就是這個頁面的 TBT 分數。
1.2 最佳實踐
用於檢測 Web 應用程式整體代碼健康狀況,包括是否包含文檔類型、圖片寬高比是否正確等等。
1.3 SEO
用於檢測搜索引擎對網頁內容的理解程度。
2. 分析需要優化的地方
瞭解了關鍵的性能指標後,就可以測量看看當前網站的性能了,
上面看到綜合評分是非常低的,Lighthouse 給出了應該從哪些地方開始優化的建議。
2.1 Performance
性能優化建議主要包括以下幾點:
-
減少未使用的 JS;
-
合理使用圖片的格式,webp 或者 avif 更快;
-
延遲載入不在視圖的圖片;
-
JS 壓縮;
-
圖片的尺寸大小應該適當;
-
減少未使用的 CSS。
Lighthouse 診斷出的網站存在的問題:
-
需要載入的資源太多太大,有 147 個請求,合計 11mb;
-
有 40 個靜態資源的緩存只有 1 小時
-
滾動事件沒有添加標記
{passive: true})
,導致需要等待偵聽器完成執行後再滾動頁面; -
圖像元素沒有設置明確的寬度和高度;
-
JS 文件太多,主線程工作量太大、JS 執行時間太長;
2.2 最佳實踐
最佳實踐方面有以下問題:
-
圖片的解析度太低,清晰度不夠;
-
沒有設置 CSP 策略。
2.3 SEO
SEO 有以下問題:
-
沒有 meta description;
-
圖片沒有 alt 屬性;
-
robots.txt 是無效的。
三、優化 Performance
根據上面 Lighthouse 報告,捋一捋項目中影響性能最大的因素,包括以下幾點:
-
體積太大,達 11mb;
-
圖片太大,圖片格式也有影響。
1. 體積優化
1.1 代碼壓縮
檢查是否還有壓縮空間,或者有無工具庫未壓縮的。
1.2 代碼分包
通過 webpack-bundle-analyzer 插件分析包體積,將一些大的 npm 包和 runtimeChunk 獨立分包,減小包體積。
1.3 組件按需載入
React.lazy + Suspense 封裝懶載入組件,路由級組件引入懶載入組件。
同時使用骨架屏作為懶載入的兜底組件,可以讓用戶感知載入更快。
在滑鼠移入導航欄時預載入路由組件,可以加快頁面展示。
1.4 工具庫按需載入
通過 import('xx').then(xx) 按需載入工具庫。
1.5 靜態資源上傳 CDN
項目內有一些 json 文件存儲的靜態數據,這部分文件上傳至 CDN,改為 fetch 的方式按需引入。
1.6 刪除不需要的資源
檢查項目中引入的 mf、npm 資源,將沒有使用到的刪除。
1.7 避免重覆的 npm 包引入
發現業務組件庫通過 npm 引入的原子組件庫,而項目本身又是通過 mf 引入的原子組件庫,相對於引入了 2 遍原子組件庫。
這時就需要改造業務組件庫,也改成用 mf 的方法引入。
1.8 避免 esm 依賴嵌套
因為 webpack 的按需載入是通過 import、export 來標記的,因此想要一個好的按需載入的效果,就需要避免依賴嵌套的問題。
1.9 圖標按需載入
原子組件庫 mf 暴露的方式會導致只用了 1 個 icon,就會載入組件庫下所有 icon 對應的 chunk,導致資源浪費。
新建一個 icon 的 npm 包用於 icon 的按需引入。
1.10 小結
通過以上優化手段,體積從 11.7mb 降低至 1.1mb,降低 10.6 倍。
優化前:
優化後:
2. 圖片優化
1.1 圖片懶載入
對非首屏的圖片採用圖片懶載入策略。
1.2 圖片尺寸
使用圖片時,設置圖片的合理尺寸。
1.3 圖片格式設置
優先使用 webp 格式圖片。
四、優化最佳實踐
1. 設置 CSP 策略
2. 設置合理的圖片的解析度
優化項目內的圖片解析度。
五、優化 SEO
1. meta description、keywords 優化
詳細的 meta description、keywords 可以加快 SEO。
<meta name="keywords" content="xx" /> <meta name="description" content="xx" />
2. 圖片加上 alt 屬性
<img src="smiley.gif" alt="Smiley face" />
六、優化前後對比
再來回顧下前後對比:
優化前,明顯的感知白屏時間長:
優化後,在清緩存的情況下也能實現秒開:
整體性能提升 270%:
七、性能監控
為了在後續的迭代過程中,保持高性能,引入內部前端監控平臺 -燭龍,可視化的監控前端性能。
第一步,載入 cdn 插件:
<script
defer
src="https://h5static.m.jd.com/act/jd-jssdk/latest/jd-jssdk.min.js"
></script>
第二步,在入口文件中,初始化 cdn 插件:
useEffect(() => {
// 初始化測速組件,在這裡可以打開一些控制的開關,如是否上報介面
if (IS_PROD) {
// @ts-ignore
jmfe.profilerInit({
flag: xxx, // 這是應用ID,需要先在燭龍申請應用
autoReport: true,
autoAddStaticReport: true,
autoAddApiReport: true,
autoAddImageReport: false, // 支持所有圖片上報,如果圖片多,切記關閉,否則存在性能問題
performanceReportTime: 8000,
profilingRate: 1,
})
}
}, [])
第三步,查看監控數據:
在燭龍平臺,小工具性能評分達 96分:
第四步,新增告警,實時監控
燭龍平臺支持多維度的告警的服務,增加性能指標相關的告警,在性能異動時,及時發現問題,優化性能。
小結
本文詳細介紹了一個前端項目優化的詳細過程,從優化前的問題分析,到具體的優化措施,最終實現了前端性能提升了近 3 倍。同時也將性能指標落到監控平臺,實現可視化的監控前端性能指標。
希望能對你有所幫助,感謝閱讀~
參考資料
作者:京東零售 唐姣
來源:京東雲開發者社區