11: 網頁生成的過程及對性能的影響
網頁生成的過程
網頁生成過程,大致可以分成五步
1. HTML代碼轉化為DOM
2. CSS代碼轉化成CSSOM(CSS Object Model)
3. 結合DOM和CSSOM,生成一棵渲染樹(包含每個節點的視覺信息)
4. 生成布局(layout),即將所有渲染樹的所有節點進行平面合成
5. 將布局繪制(paint)在屏幕上
在這五步里面,第一步到第三部都非常快,第四步和第五步很耗時
。
重排和重繪
網頁生成的時候,至少會渲染一次。而我們需要關注的是用戶訪問過程中,那些會導致網頁重新渲染的行為:
· 修改DOM
· 修改樣式表
· 用戶事件(例如鼠標懸停,頁面滾動,輸入框輸入文字等)
重新渲染,就涉及重排
和重繪
重排(reflow)
即重新生成布局,重排必然導致重繪,如元素位置的改變,就會觸發重排和重繪。
重繪(repaint)
即重新繪制,需要注意的是,重繪不一定需要重排
,比如改變某個元素的顏色,就只會觸發重繪,而不會觸發重排。
對於性能的影響
重排和重繪會不斷觸發,這是不可避免的,但是它們非常消耗資源,是導致網頁性能低下的根本原因。
提高網頁性能,就是要降低重排和重繪的頻率和成本,盡量少觸發重新渲染
。
大部分瀏覽器通過隊列化修改
和批量顯示
優化重排版過程。然而有些操作會強迫刷新並要求所有計划改變的部分立刻應用。
本資料作為dom操作最佳實踐的補充
刷新率
網頁動畫的每一幀(frame)都是一次重新渲染,每秒低於24幀
的動畫,人眼就能感受到停頓。一般的網頁動畫,需要達到每秒30幀到60幀的頻率,才能比較流暢
。
而大多數顯示器的刷新頻率是60Hz
,為了與系統一致,以及節省電力,瀏覽器會自動按照這個頻率,刷新動畫。所以,如果網頁能夠做到每秒60幀,就會跟顯示器同步刷新,達到最佳的視覺效果。這意味着,一秒之內進行60次重新渲染,每次重新渲染的時間不能超過16.66ms
。
刷新率
FPS(frame per second),即一秒之間能夠完成多少次重新渲染
開發者工具的Timeline面板
通過JS代碼實現 FPS 的檢測
這個時候 我們拿 我去年寫的 Vuejs 中文社區的網站。來試一試
打開控制台執行下面的代碼:
// 返回是否 有 requestAnimationFrame 方法 1000ms 會執行 60 次
var rAF = function () {
return (
window.requestAnimationFrame ||
window.webkitRequestAnimationFrame ||
function (callback) {
window.setTimeout(callback, 1000 / 60);
}
);
}();
var frame = 0;
var allFrameCount = 0;
var lastTime = Date.now();
var lastFameTime = Date.now();
var loop = function () {
var now = Date.now();
var fs = (now - lastFameTime);
var fps = Math.round(1000 / fs);
lastFameTime = now;
// 不置 0,在動畫的開頭及結尾記錄此值的差值算出 FPS
allFrameCount++;
frame++;
if (now > 1000 + lastTime) {
var fps = Math.round((frame * 1000) / (now - lastTime));
console.log(`${new Date()} 1S內 FPS:`, fps);
frame = 0;
lastTime = now;
};
rAF(loop);
}
loop();
然后我們看到了如下的顯示:
Mon Aug 13 2018 20:14:44 GMT+0800 (中國標准時間) 1S內 FPS: 60
Mon Aug 13 2018 20:14:45 GMT+0800 (中國標准時間) 1S內 FPS: 60
Mon Aug 13 2018 20:14:46 GMT+0800 (中國標准時間) 1S內 FPS: 55
Mon Aug 13 2018 20:14:47 GMT+0800 (中國標准時間) 1S內 FPS: 60
Mon Aug 13 2018 20:14:48 GMT+0800 (中國標准時間) 1S內 FPS: 60
Mon Aug 13 2018 20:14:49 GMT+0800 (中國標准時間) 1S內 FPS: 60
Mon Aug 13 2018 20:14:50 GMT+0800 (中國標准時間) 1S內 FPS: 58
Mon Aug 13 2018 20:14:51 GMT+0800 (中國標准時間) 1S內 FPS: 60
Mon Aug 13 2018 20:14:52 GMT+0800 (中國標准時間) 1S內 FPS: 60
Mon Aug 13 2018 20:14:53 GMT+0800 (中國標准時間) 1S內 FPS: 60
Mon Aug 13 2018 20:14:54 GMT+0800 (中國標准時間) 1S內 FPS: 56
Mon Aug 13 2018 20:14:55 GMT+0800 (中國標准時間) 1S內 FPS: 59
剛剛好 屏幕的刷新率就在 60 fps 左右, 很流暢。
寫在最后
在現在 Vue 、Recat 、 Angular 三大框架盛行的當今,最原始的 瀏覽器渲染網頁的時候就做哪些事情或許我們已經忘記了一些。
這篇文章也只是做一個基礎的記憶,網頁是如何進行渲染的,在這三大框架的下,虛擬DOM 的出現,對於網頁加載有什么優勢?
重排、重繪的時候就做哪些事情? 頁面渲染的性能瓶頸往往出現在哪里? 我們如何能夠減少這些性能消耗的操作?
這些疑問,都是這邊文件做的一個解釋。
GitHub 地址:(歡迎 star 、歡迎推薦:)