內容來源:2018 年 6 月 30 日,餓了麼前端主管向勇在「餓了麼技術沙龍・第27彈 【前端專場】」進行《h5渲染性能一瞥》演講分享。IT 大咖說(微信id:itdakashuo)做爲獨家視頻合做方,經主辦方和講者審閱受權發佈。前端
閱讀字數:2488 | 7分鐘閱讀面試
獲取嘉賓演講視頻及PPT:suo.im/4SkvOx
性能優化
前端性能按照類型來分主要分爲加載性能和渲染性能。加載性能對於首屏的展現及其重要,而渲染性能對於頁面加載完成後的交互體驗極其重要。但目前絕大部分同窗在提到前端性能的優化時都會默認等同於對加載性能的優化,而忽略了渲染性能。本次議題就從幾個比較常見的角度聊聊開發中會無心識碰到的渲染性能問題。微信
在將H5和native進行對比的時候,咱們一般能想到的一點就是「快」,H5相對於native開發和上線都會快一些,通常的活動頁面和非關鍵頁面更多的傾向於H5來開發。前端性能
固然H5也有相應的缺點,它的加載和操做會慢一些,抽象來看就是性能問題。加載慢對應的是加載性能,操做慢對應的是渲染性能。加載性能可被定義爲頁面首次加載時候的性能,這方面的優化方案主要有靜態資源壓縮、懶加載、雪碧圖、CDN、server push等。佈局
渲染性能可被定義爲頁面進行操做/交互時候的性能,對於這方面的優化可能並不太容易想到。我在面試的時候也常常會問面試者關於性能優化的問題,不過大部分提到的優化方案都是關於加載性能,少部分會提到GPU加速,相對來講這部分同窗的CSS技能會高一些。性能
通常一次渲染都會通過JavaScript > style > layout > paint > compoasite這樣的過程。在作動畫的時候能夠進行優化,將layout和paint省略掉,這實際上是將作動畫的元素提高爲一個單獨的層。flex
渲染性能的優化能夠針對渲染過程當中的每一步來作,下面列出了google開發者論壇中提到的具體優化措施。優化
優化JS執行(JS)動畫
縮小樣式計算的範圍並下降其複雜性(style)
避免大型、複雜的佈局和佈局抖動(layout、paint)
使用輸入處理程序去除抖動(layout、paint)
堅持僅合成器的屬性和管理層技術(composite)
簡化繪製的複製度、減少繪製區域(paint、composite)
上面加粗的兩個優化手段能夠總結爲層的優化,也就是開啓GPU加速。這裏咱們先假設一個場景,在一個頁面中存在兩個水平排列的元素一、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值小於下方兄弟元素,且他們有重疊,則下方兄弟元素也會被提高爲合成層。
上圖是餓了麼頁面的簡化場景,區域1是可滑動動畫區,使用flex佈局實現,區域2是店鋪列表,區域3是店鋪信息,這兩個區域都添加了position:relative。
這種實現方式沒有指定浮動層的z-index值,所以在區域1進行滑動的時候,下方的每一個店鋪列表都會被提高爲單獨的層。在爲區域1設置position:relative和z-index:1(高於下層)以後下方的層就不會再被提高了(此時下層z-index未設置)。
注意圖中標記區域,當點擊展開/收起活動的小三角的時候會有一個旋轉180度的交互效果,相信你們對此都很熟悉。這種效果實現起來也很簡單,設置transition過渡屬性就能完成。
在實際操做的時候查看層級會發現,每一個商店列表都被提高成單獨的層且有不少嵌套。形成此問題的緣由和前面的案例相似,主要仍是沒有給擁有過渡動畫效果的小三角元素添加z-index值,解決方案一樣是爲動畫元素設置z-inde。
這一系列的問題涉及到一個概念:層壓縮,即若是多個渲染層同一個合成層重疊時候,這些渲染層會被壓縮到一個GraphicsLayer中。
另外若是元素有動畫/過渡效果,可未指定層級順序高於下方浮動層,此時會假定下方的浮動層在動畫期間會受影響,從而沒法被壓縮。
通常咱們編寫頁面的時候都會爲頭部和底部設置固定浮動,這涉及到減小繪製區域的優化策略。在沒有設置浮動的狀況下,每次頁面滾動頭部和底部就會被從新渲染,解決方案是設置浮動後將這些浮動的頭部和底部提高爲單獨的層。