聽餓了麼前端主管如何解析H5渲染性能

聽餓了麼前端主管如何解析H5渲染性能

內容來源:2018 年 6 月 30 日,餓了麼前端主管向勇在“餓了麼技術沙龍・第27彈 【前端專場】”進行《h5渲染性能一瞥》演講分享。IT 大咖說作為獨家視頻合作方,經主辦方和講者審閱授權發佈。

閱讀字數:2488 | 7分鐘閱讀

嘉賓演講視頻及PPT,請複製:http://t.cn/RkD5wJq,粘貼至瀏覽器即可。

聽餓了麼前端主管如何解析H5渲染性能

摘要

前端性能按照類型來分主要分為加載性能和渲染性能。加載性能對於首屏的展示及其重要,而渲染性能對於頁面加載完成後的交互體驗極其重要。但目前絕大部分同學在提到前端性能的優化時都會默認等同於對加載性能的優化,而忽略了渲染性能。本次議題就從幾個比較常見的角度聊聊開發中會無意識碰到的渲染性能問題。

H5 VS Native

在將H5和native進行對比的時候,我們通常能想到的一點就是“快”,H5相對於native開發和上線都會快一些,一般的活動頁面和非關鍵頁面更多的傾向於H5來開發。

當然H5也有相應的缺點,它的加載和操作會慢一些,抽象來看就是性能問題。加載慢對應的是加載性能,操作慢對應的是渲染性能。加載性能可被定義為頁面首次加載時候的性能,這方面的優化方案主要有靜態資源壓縮、懶加載、雪碧圖、CDN、server push等。

渲染性能可被定義為頁面進行操作/交互時候的性能,對於這方面的優化可能並不太容易想到。我在面試的時候也經常會問面試者關於性能優化的問題,不過大部分提到的優化方案都是關於加載性能,少部分會提到GPU加速,相對來說這部分同學的CSS技能會高一些。

渲染

一般一次渲染都會經過JavaScript > style > layout > paint > compoasite這樣的過程。在做動畫的時候可以進行優化,將layout和paint省略掉,這其實是將做動畫的元素提升為一個單獨的層。

渲染性能的優化可以針對渲染過程中的每一步來做,下面列出了google開發者論壇中提到的具體優化措施

  • 優化JS執行(JS)
  • 縮小樣式計算的範圍並降低其複雜性(style)
  • 避免大型、複雜的佈局和佈局抖動(layout、paint)
  • 使用輸入處理程序去除抖動(layout、paint)
  • 堅持僅合成器的屬性和管理層技術(composite)
  • 簡化繪製的複製度、減小繪製區域(paint、composite)

層的優化

上面加粗的兩個優化手段可以總結為層的優化,也就是開啟GPU加速。這裡我們先假設一個場景,在一個頁面中存在兩個水平排列的元素1、2,他們分別位於左右兩端,我們要做的是將1移動到2的位置。對此最簡單的方案是設置position並改變right或left的值。第二種方式是使用transform:translateX,並加上 will-change: transform/transform: translate(0)將它提升為單獨的層,這種方案的好處在於啟用了GPU加速。

這樣看來只要應用GPU加速就能很好的解決動畫優化問題,但是實際應用中的頁面往往要比上面所描述的場景複雜的多。就拿餓了麼的H5頁面來說,它除了有輪播外還涉及到頁面滾動、點擊展開,返回頂部等。當開啟layer borders查看時會發現滑動的過程中如果輪播圖正在播放整個頁面就會創建很多不必要的層。另外開啟Paint flashing查看重繪情況時也會發現每次輪播圖播放都會導致整個頁面重繪。這種問題在低端手機上可能會造成閃屏,需要額外注意。解決方案其實前面也提到過就是要將做動畫的元素提升為一個單獨的層(合成層)

之前說過動畫的問題有兩種解決方案,如果這兩個方案結合在一起又會怎麼樣呢,也就是將position和will-change寫在同一個元素上,這在實際寫代碼的過程中是很容易碰到的。由此引出了新的問題,浮動元素(渲染層)和合成層的關係。對此我個人做了下總結:

若合成層的z-index值小於下方兄弟元素,且他們有重疊,則下方兄弟元素也會被提升為合成層。

聽餓了麼前端主管如何解析H5渲染性能

上圖是餓了麼頁面的簡化場景,區域1是可滑動動畫區,使用flex佈局實現,區域2是店鋪列表,區域3是店鋪信息,這兩個區域都添加了position:relative。

這種實現方式沒有指定浮動層的z-index值,因此在區域1進行滑動的時候,下方的每個店鋪列表都會被提升為單獨的層。在為區域1設置position:relative和z-index:1(高於下層)之後下方的層就不會再被提升了(此時下層z-index未設置)。

層爆炸

聽餓了麼前端主管如何解析H5渲染性能

注意圖中標記區域,當點擊展開/收起活動的小三角的時候會有一個旋轉180度的交互效果,相信大家對此都很熟悉。這種效果實現起來也很簡單,設置transition過渡屬性就能完成。

在實際操作的時候查看層級會發現,每個商店列表都被提升成單獨的層且有很多嵌套。造成此問題的原因和前面的案例類似,主要還是沒有給擁有過渡動畫效果的小三角元素添加z-index值,解決方案同樣是為動畫元素設置z-inde。

這一系列的問題涉及到一個概念:層壓縮,即如果多個渲染層同一個合成層重疊時候,這些渲染層會被壓縮到一個GraphicsLayer中。

另外如果元素有動畫/過渡效果,可未指定層級順序高於下方浮動層,此時會假定下方的浮動層在動畫期間會受影響,從而無法被壓縮。

減少繪製區域

一般我們編寫頁面的時候都會為頭部和底部設置固定浮動,這涉及到減少繪製區域的優化策略。在沒有設置浮動的情況下,每次頁面滾動頭部和底部就會被重新渲染,解決方案是設置浮動後將這些浮動的頭部和底部提升為單獨的層。

以上為今天的分享內容,謝謝大家!


分享到:


相關文章: