將圖片資源轉至base64格式後可直接放入頁面作為首屏直出,也可以放入css檔案中,減少請求,以加快首屏的呈現速度。
不過圖片base64化,將帶來一個臃腫的html或css檔案,是否會影響頁面的渲染效能,瀏覽器又支援如何呢?
如何統計?
通過Navigation Timing記錄的關鍵時間點來統計頁面完成所用的時間,並通過Chrome開發工具來跟蹤細節
1 2 3 4 5 |
var timing = window.performance.timing timing.domLoading //瀏覽器開始解析 HTML 文件第一批收到的位元組 timing.domInteractive // 瀏覽器完成解析並且所有 HTML 和 DOM 構建完畢timing.domContentLoadedEventStart //DOM 解析完成後,網頁內資源載入開始的時間 timing.domContentLoadedEventEnd //DOM 解析完成後,網頁內資源載入完成的時間(如 JS 指令碼載入執行完畢) timing.domComplete //網頁上所有資源(圖片等) 下載完成,且準備就緒的時間 |
以上定義來自chrome官方文件,在其它環境下也許會有差異,從測試結果看,下面的build時間在android+微信環境中一直是0,對此可能是因為渲染機制差別,此處不做深入測試。除osx+chrome之外環境的資料僅作參考。
1 2 |
build = timing.domComplete - timing.domContentLoadedEventStart //間隔記錄網頁內資源載入和呈現時間。 complete = timing.domComplete - timing.domLoading //頁面接收到資料開始到呈現完畢的總時間。 |
場景1,內嵌至css檔案中
1、原生引入圖片連結做背景圖
一張大小為50kb的jpg格式圖片,應用到9×15=135個dom做背景圖,模擬雪碧圖的模式,多個節點引用同一張圖片做背景,(示例)如圖。
測試環境
:Mac OS X EI Capitan 10.xx + Chrome 48.xx
其它輔助測試機器
: iPhone 6 plus iOS 9.xx; 魅族Note Android 4.xx
實際使用過程中,其它版本和機型的Android手機還有待測試
關閉快取狀態下,build:150ms | complete: 200ms(總時間受網路狀態等因素影響,資料做比較用)
開啟快取狀態下,build: 7ms | complete: 59ms(包括以下穩定狀態下多次測試的平均值,截圖為最接近平均值的狀態,預設資料來自Mac+Chrome[48.XX版本])
測試環境 | build(單位:ms) | complete(單位:ms) |
---|---|---|
OS X+Chrome | 7 | 59 |
iOS+微信 | 45 | 90 |
OS X+Safari | 50 | 100 |
Android+微信 | 0 | 120 |
2、引入base64格式圖片做背景圖
將上面50kb大小的jpg圖片轉換為base64格式,加在css檔案中。
關閉快取狀態下,build:80ms | complete: 280ms
開啟快取狀態下,build: 160ms | complete: 210ms
測試環境 | build(單位:ms) | complete(單位:ms) |
---|---|---|
OS X+chrome | 160 | 210 |
iOS+微信 | 35 | 100 |
OS X+Safari | 9 | 90 |
Android+微信 | 12 | 150 |
3、調整圖片體積
調整上面圖片的(壓縮品質)體積,base64化後,對應的css檔案大小也跟著改變
圖片大小 | 10kb | 20kb | 45kb | 100kb | 180kb |
---|---|---|---|---|---|
對應css檔案大小 | 27kb | 42kb | 76kb | 150kb | 260kb |
Rendering時間 | 30ms | 46ms | 81ms | 156ms | 258ms |
4、調整引用次數
50kb大小的圖片,base64化後,調整引用圖片做背景圖的dom的個數
引用次數 | 10 | 20 | 50 | 100 | 135 |
---|---|---|---|---|---|
Rendering時間 | 15ms | 19ms | 44ms | 74ms | 83ms |
分析和小結:
在OSX+Chrome環境下,將50kb的圖片base64後放入樣式中,build過程拉長了約20倍,使用Timeline工具可以看到,計算樣式阻塞了整個過程。
- 比起直接引入圖片地址,css檔案中引入base64格式的圖片對樣式渲染的效能消耗明顯,如果大量使用,會帶來耗電和發熱的問題,需謹慎使用。
- Rendering消耗的時間同css檔案大小、引用次數幾乎成正比(未測試其它極限情況),在網路條件優質的4G環境,50~70ms的RTT(往返時延)情況下,通常行動網路的狀況會更差,對於首屏優化,合適的使用還是很值得的。
- 圖片轉成base64編碼後,文件大小較原檔案大了一些,而經過 gzip 後兩者幾乎沒有區別。
場景2,內嵌至js檔案中
1、原生方式直接載入多張圖片
大小10~70kb共9張圖片。總大小約300kb
關閉快取:build: 300ms | complete: 310ms
開啟快取:build: 110ms | complete: 120ms
測試環境 | build(單位:ms) | complete(單位:ms) |
---|---|---|
OS X+Chrome | 110 | 120 |
iOS+微信 | 50 | 100 |
OS X+Safari | 148 | 150 |
Android+微信 | 50 | 100 |
2、轉換成base64格式,合併請求
將上面的圖片轉成base64後,放在js檔案中,載入進來。
關閉快取:build: 0ms | complete: 400ms
開啟快取:build: 0ms | complete: 80ms
測試環境 | build(單位:ms) | complete(單位:ms) |
---|---|---|
OSX+Chrome | 110 | 120 |
iOS+微信 | 0 | 35 |
OS X+Safari | 7 | 70 |
Android+微信 | 0 | 250 |
3、比較不同網速下同步請求和合並請求的載入效率
使用上述1、2的測試demo分別在3G、4G網速條件下測試結果如下:
- 在網路環境差的情況下,合併請求明顯縮短了整個載入時間;
- 在網路環境較好的WIFI和4G下則差別不大。
測試環境 | 圖片直接載入 complete(單位:ms) | base64合併請求 complete(單位:ms) |
---|---|---|
3G | 6000 | 4500 |
4G | 450 | 400 |
WIFI | 320 | 340 |
分析和小結:
base64後的的js資源達381kb,在一個執行緒里載入,消耗大量時間,從統計結果看,在渲染效能差異上並沒有場景1那麼明顯。
但有快取的情況下,頁面渲染完成的速度甚至更快。
從Timeline裡看到細節,解析這個近400kb的js檔案對整個渲染過程造成了一定壓力,不過總共40ms的解析時間是完全可以接受的。
- 從html裡直直接引用圖片連結和base64圖片對渲染效能的影響幾乎沒有區別,在網路條件差的情況下,合併請求卻能大大提高載入效率;
- 直接引用至html,無法快取,將base64後的圖片資源放在js檔案中管理,方便設定快取。
- 有一個缺點就是圖片資源base64化需要擴充套件構建工具來支援。
使用建議
- 圖片資源的base64編碼進css檔案會帶來一定的效能消耗,需謹慎使用。
- 將圖片資源編碼進js檔案中,管理和預載入H5應用的圖片資源,合理的合併請求可以大大提高頁面體驗。