瀏覽器的渲染與頁面優化
一個高流𣈱度的網頁,就是一件藝術作品。網頁工匞必須具備三元素知識,:HTML、Javascript 和 CSS。除了寫出高質量的程式碼,也要確保相關的第三方程式碼是高品質的。
這篇文章,是整理2位巨人 Paul Lewis 和 Ilya Grigorik 的文章,在討論瀏覽器的渲染過程,和 Rendering Tree 對生成頁面組成。當電腦的速度變慢,我們至少知道要加入更強大的 CPU 或 RAM,才能對症下藥。瀏覽器的優化一樣要對症下藥。
1. 記住 60fps
大部份的裝置:手機和電腦,畫面每秒更新60次 (60 frame pre second 又叫60幀)。當網頁要完成一個動畫,或完成滾動動作,瀏覽器需要協調網頁和裝置,每一次更新畫面時,放入對應的新圖片,以完成動畫。
理論上每幀所消耗的成本是 16ms (1 second / 60 = 16.66ms),實際上瀏覽器每秒七手八腳地更新 60張新圖片,時間緊迫,我們必須在 10ms 內完成處理變動的圖片。當無法在 10ms 內完成工作, fps 就會下降,出現畫面遲鈍;當程式的 fps 高於 60fps,就會造成資源浪費(jank),用戶體驗差。所以最優化的狀況是每秒更新 60次 (60fps)。
2. 像素化五步曲
像素化過程 The pixel pipeline
關於渲染,瀏覽器可分成5個部份,Pixel Pipeline (像素化過程),也是網頁流𣈱度進行優化的5把鑰匙。
- JavaScript. 基本上 Javascript 用作處理網頁畫面的改變,可以是動作,資料的排序或新增 DOM 元素。
- 樣式運算 Style calculations. 這個過程負責整理出CSS 規則(CSS Rules) 放到符合選擇器 (Selector) 的 DOM 元素。
例如:.headline
or.nav > .nav__item
. - 佈局 Layout. 瀏覽器精確地計算每個元素(Element)在頁面的位置,大小。而且也會運算元素間的相互效應,和樣式之間的繼承。例如
<body>
元素的width
由上至下影響子元素的width
. - 畫 Paint. 想像它是拿著筆上色的過程,對螢幕像素填上顏色的步驟。他把文字寫出來,把圖片畫出來,顏色、邊框和陰影呈現在 DOM 元素上。
畫的過程出現一層疊一層的畫,應為 Layer (圖層)。 - 合成 Compositing. 當畫面上的元素被畫好了,放在不同的圖層。 而且圖層正在等待被放置到網頁的正確位置,準備好被正確地渲染。
五個步驟網頁資源浪費(Jank)的嫌疑犯,就是上面提到的五個步驟。你必須全盤掌握你所寫的程式碼,到底在將像數化過程(Pixel Pipeline)中產生什麼化學反應。
實際情況下, 不必無時無刻觀察着將像化過程的每個細節,一般修改網頁內容,可以收窄為3種渲染方式。
2.1. JS / CSS > Style > Layout > Paint > Composite
影響佈局(Layout),是徹底上的把頁面重畫一次
當網頁上的元素, 被修改到 Layout Property,例如 width, height, 或 left top,瀏覽器需要檢查所有的元素,因為元素間的位置和大小是相互影響,導致整頁需要重再佈局一次,再畫一次,再合成一次
2.2. JS / CSS > Style > Paint > Composite
改變 畫(Paint) 的相關屬性,成本比較底。
修改的是畫 (Paint) 相關屬性,例如 background image
, text color
, 或 shadows
,一些和佈局 (Layout) 獨立無關的改變,瀏覽器會略過佈局,由畫(paint)步驟開始更新頁面。
2.3. JS / CSS > Style > Composite
既不是佈局(Layout),又不是畫(Paint),就是最輕量。
像素化五步曲中,最後一步合成(Composite)的變動是最便宜。例如常常出現的頁面上下滾動和元件的動畫,大家最渴望見到的情況是,在滾動和動畫出現的生命週期中,影響到的屬性只有合成。
瀏覧器既不需要更新佈局,又不需要畫一次。
Remark
visibility: hidden
和 display: none
的不同處。前者在畫面上佔有空間,被渲染成一個空的元素,不被看到;後者將會從Render Tree 中消失。
CSSOM & DOM trees
CSSOM 樹 和 DOM 樹的組合,成為渲染樹 (Render Tree),它是用來運算元素佈局 (Layout) 和像素化(Pixel Pipeline) 上色到屏幕,而且最優化這一系列的過程。
- DOM Tree 和 CSSOM Tree 組合成 Render tree.
- Render tree 只包含將會渲染的節點 (Nodes)
- 佈局、畫和合成就會按照 Render Tree 的安排而動工
Reference
https://developers.google.com/web/fundamentals/performance/rendering/