瀏覽器渲染頁面的原理及流程css
瀏覽器將域名經過網絡通訊從服務器拿到html文件後,如何渲染頁面呢?html
1.根據html文件構建DOM樹和CSSOM樹。構建DOM樹期間,若是遇到JS,阻塞DOM樹及CSSOM樹的構建,優先加載JS文件,加載完畢,再繼續構建DOM樹及CSSOM樹。瀏覽器
2.構建渲染樹(Render Tree)。緩存
3.頁面的重繪(repaint)與重排(reflow,也有稱迴流)。頁面渲染完成後,若JS操做了DOM節點,根據JS對DOM操做動做的大小,瀏覽器對頁面進行重繪或是重排。服務器
1、構建DOM樹及CSSOM樹網絡
1.1構建DOM樹async
HTML 文檔中的全部內容皆是節點,各節點之間擁有層級關係,如父子關係、兄弟關係等,彼此相連,構成DOM樹。最多見的幾種節點有:文檔節點、元素節點、文本節點、屬性節點、註釋節點。佈局
DOM節點樹中節點與HTML文檔中內容一一對應,DOM樹構建過程:讀取html文檔,將字節轉換成字符,肯定tokens(標籤),再將tokens轉換成節點,以節點構建 DOM 樹。以下圖所示:性能
1.2構建CSSOM樹字體
CSS文檔中,全部元素皆是節點,與HTML文件中的標籤節點一一對應。CSS中各節點之間一樣擁有層級關係,如父子關係、兄弟關係等,彼此相連,構成CSSOM樹。
在構建DOM樹的過程當中,在 HTML 文檔的 head 標籤中遇到 link 標籤,該標籤引用了一個外部CSS樣式表。因爲預見到須要利用該CSS資源來渲染頁面,瀏覽器會當即發出對該CSS資源的請求,並進行CSSDOM樹的構建。
CSSOM樹構建過程與DOM樹構建流程一致:讀取CSS文檔,將字節轉換成字符,肯定tokens(標籤),再將tokens轉換成節點,以節點構建 CSSOM 樹。以下圖所示:
.CSS文件,又名層疊樣式表。當CSSOM樹生成節點時,每個節點首先會繼承其父節點的全部樣式,層疊覆蓋,而後再以"向下級聯"的規則,爲該節點應用更具體的樣式,遞歸生成CSSOM樹。譬如,上右圖中第二層的p節點,有父節點body,所以該p將繼承body節點的樣式:"font-size: 16px;"。而後再應用該p節點自身的樣式:"font-weight: bold;"。因此最終該p節點的樣式爲:"font-size: 16px;font-weight: bold;"。
1.3加載JS
若在構建DOM樹的過程當中,當 HTML 解析器遇到一個 script 標記時,即遇到了js,將當即阻塞DOM樹的構建,將控制權移交給 JavaScript 引擎,等到 JavaScript 引擎運行完畢,瀏覽器纔會從中斷的地方恢復DOM樹的構建。
其根本緣由在於,JS會對DOM節點進行操做,瀏覽器沒法預測將來的DOM節點的具體內容,爲了防止無效操做,節省資源,只能阻塞DOM樹的構建。譬如,若不阻塞DOM樹的構建,若JS刪除了某個DOM節點A,那麼瀏覽器爲構建此節點A花費的資源就是無效的。
若在HTML頭部加載JS文件,因爲JS阻塞,會推遲頁面的首繪。爲了加快頁面渲染,通常將JS文件放到HTML底部進行加載,或是對JS文件執行async或defer加載。
二.構建渲染樹
渲染樹(Render Tree)由DOM樹、CSSOM樹合併而成,但並非必須等DOM樹及CSSOM樹加載完成後纔開始合併構建渲染樹。三者的構建並沒有前後條件,亦非徹底獨立,而是會有交叉,並行構建。所以會造成一邊加載,一邊解析,一邊渲染的工做現象。
構建渲染樹,根據渲染樹計算每一個可見元素的佈局,並輸出到繪製流程,將像素渲染到屏幕上。
三.頁面的重繪(repaint)與重排(reflow)
3.1重繪(repaint):屏幕的一部分要重繪。渲染樹節點發生改變,但不影響該節點在頁面當中的空間位置及大小。譬如某個div標籤節點的背景顏色、字體顏色等等發生改變,可是該div標籤節點的寬、高、內外邊距並不發生變化,此時觸發瀏覽器重繪(repaint)。
3.2重排(reflow):也有稱迴流,當渲染樹節點發生改變,影響了節點的幾何屬性(如寬、高、內邊距、外邊距、或是float、position、display:none;等等),致使節點位置發生變化,此時觸發瀏覽器重排(reflow),須要從新生成渲染樹。譬如JS爲某個p標籤節點添加新的樣式:"display:none;"。致使該p標籤被隱藏起來,該p標籤以後的全部節點位置都會發生改變。此時瀏覽器須要從新生成渲染樹,從新佈局,即重排(reflow)。
注意:重排必將引發重繪,而重繪不必定會引發重排。
什麼時候回引發重排?
當頁面佈局和幾何屬性改變時就須要重排。下述狀況會發生瀏覽器重排:
一、添加或者刪除可見的DOM元素;
二、元素位置改變——display、float、position、overflow等等;
三、元素尺寸改變——邊距、填充、邊框、寬度和高度
四、內容改變——好比文本改變或者圖片大小改變而引發的計算值寬度和高度改變;
五、頁面渲染初始化;
六、瀏覽器窗口尺寸改變——resize事件發生時;
3.3如何減小和避免重排
Reflow 的成本比 Repaint 的成本高得多的多。一個節點的 Reflow 頗有可能致使子節點,甚至父節點以及兄弟節點的 Reflow 。在一些高性能的電腦上也許還沒什麼,可是若是 Reflow 發生在手機上,那麼這個過程是延慢加載和耗電的。----瀏覽器的渲染原理簡介
1. 直接改變className,若是動態改變樣式,則使用cssText(考慮沒有優化的瀏覽器);
2. 讓要操做的元素進行」離線處理」,處理完後一塊兒更新;
a) 使用DocumentFragment進行緩存操做,引起一次迴流和重繪;
b) 使用display:none技術,只引起兩次迴流和重繪;
c) 使用cloneNode(true or false) 和 replaceChild 技術,引起一次迴流和重繪;
3.不要常常訪問會引發瀏覽器flush隊列的屬性,若是你確實要訪問,利用緩存;
4. 讓元素脫離動畫流,減小回流的Render Tree的規模;