解析html网页原理,深入浅出浏览器渲染原理
一、前言
瀏覽器的內核是指支持瀏覽器運行的最核心的程序,分為兩個部分,一是“渲染引擎”,二是“JS引擎”。
渲染引擎在不同的瀏覽器也不是都相同的,比如:
Firefox(火狐瀏覽器)中使用 Gecko; Chrome和safari中使用 WebKit
復制代碼
本文主要介紹關于WebKit的渲染引擎內容和相關問題。
本文圖解:
二、瀏覽器工作大體流程
主要分為三個部分:
瀏覽器解析
資源文件解析:
1. HTML/SVG/XHTML,事實上,Webkit有三個C++的類對應這三類文檔。解析這三種文件會產生一個DOM Tree
2. CSS,解析CSS會產生CSS規則樹
3. Javascript,腳本,主要是通過DOM API和CSSOM API來操作DOM Tree和CSS Rule Tree
復制代碼解析完成后,瀏覽器引擎會通過DOM Tree 和 CSS Rule Tree來構造Rendering Tree
1. Rendering Tree 渲染樹并不等同于DOM樹,因為一些像Header或display:none的東西就沒必要放在渲染樹中了
2. CSS 的 Rule Tree主要是為了完成匹配并把CSS Rule附加上Rendering Tree上的每個Element。也就是DOM結點。也就是所謂的Frame
3. 然后計算每個Frame(也就是每個Element)的位置,這又叫layout和reflow過程
復制代碼調用操作系統Native GUI的API繪制
三、構建DOM
瀏覽器會遵守一套步驟將HTML文件轉換為DOM樹,大概可以分為幾個步驟
瀏覽器從磁盤或網絡讀取HTML的原始字節,并根據文件的指定編碼(比如UTF-8)將它們轉換成字符串。
網絡中傳輸的內容其實都是0和1這些字節數據,當瀏覽器收到這些字節數據后,會將字節數據變成字符串,也就是代碼
復制代碼將字符串轉換成Token,例如: 、
等,Token中會標識出當前Token是“開始標簽”或是“結束標簽”亦或是“文本”等信息。
那么節點與節點之間的關系如何維護?
事實上,這就是Token要標識“起始標簽” 和“結束標簽”等標識的作用
復制代碼
例如: "title" Token的起始標簽和結束標簽之間的節點肯定都是"head"的子節點。
在上圖中描述了節點之間的關系,例如: “Hello”Token位于“title”開始標簽與“title”結束標簽之間,表明“Hello”Token是“title”Token的子節點。同理“title”Token是“head”Token的子節點
復制代碼生成節點對象并構建DOM
事實上,構建DOM的過程中,不是等所有token都轉換完成后再去生成節點對象,而是一邊生成token 一邊消耗token來生成節點對象。
復制代碼
也就是說,每個Token被生成之后,,會立刻消耗這個Token創建出節點對象。需要注意的是,有結束標簽標識的Token不會創建節點對象。
例如:這段HTML文本
Web page parsingWeb page parsing
This is an example Web page.
復制代碼
上述文本解析的時候,會如下圖示:
三、構建CSSOM
DOM會捕獲頁面的內容,但瀏覽器需要知道頁面該如何展示,所以就需要構建CSSOM。
構建CSSOM的過程和構建DOM的過程非常相似,當瀏覽器收到一段css,瀏覽器需要做的是識別出token,然后構建節點并生成CSSOM。
在這個過程中,瀏覽器會確定下每一個節點的樣式是什么,并且這一過程其實很消耗資源的,因為樣式你可以自行設置給某個節點,也可以通過繼承獲得。
在這一過程中,瀏覽器得遞歸CSSOM樹,然后確定具體的元素到底是什么樣式。
復制代碼
注意:
CSS匹配HTML元素是一個相當復雜和有性能問題的事情,所以,DOM樹要小,CSS盡量用id和class,千萬不要過渡層疊下去。
復制代碼
四、構建“樹”
當我們生成DOM樹和CSSOM樹以后,就需要將這兩棵樹組合為“渲染樹”
在這個一個過程中,不是簡單的"樹" 合并就可以了。渲染樹只會包括需要顯示的節點和這些節點的樣式信息 ,如果某個節點是 display: none的,那么就不會在渲染樹中顯示
五、布局與繪制
當瀏覽器生成“渲染樹”以后,就會根據渲染樹來進行布局(也稱作回流)。在這個階段瀏覽器要做的事情就是要弄清楚各個節點在頁面中的確切位置和大小。 通常這一行為也稱為“自動重排”。
布局流程的輸出是一個“盒模型”,它會精確地捕獲每個元素在視口內的確切位置和尺寸,所有相對測量值都將轉換為屏幕上的絕對像素。
布局完成后,瀏覽器會立即發出“Paint Setup” 和 “Paint” 事件,將渲染樹轉換成屏幕上的像素。
六、問題討論
問題一、渲染過程中遇到JS文件怎么處理?
JavaScript的加載、解析與執行會阻塞DOM的構建,也就是說, 在構建DOM時,HTML解析器若遇到了JavaScript,那么它會暫停構建DOM,將控制權移交給JavaScript引擎,等JavaScript引擎運行完畢,瀏覽器再從中斷的地方恢復DOM構建。
也就是說,如果想首屏頁面渲染的越快,就越不該在首屏加載js文件,這也是建議將 'script' 標簽放在 'body' 底部的原因。
當然在當下,并不是說script標簽必須放在底部,可以給script 標簽添加 defer或 async 屬性。
復制代碼
JS文件不只是阻塞DOM的構建,它會導致CSSOM也阻塞DOM的構建。
原本DOM和CSSOM的構建是互不影響的,但是一旦引入了JavaScript,CSSOM也開始阻塞DOM的構建,只有CSSOM構建完畢后,DOM再恢復DOM構建。
為何引入JavaScript就會發生這種情況?
主要是因為JavaScript不只是可以改變DOM,它還可以更改樣式,也就是它可以更改CSSOM。
而不完整的CSSOM是無法使用的,但JavaScript中想訪問CSSOM并更改它,那么在執行JavaScript時,必須能拿到完整的CSSOM。
所以就導致了一個現象,如果瀏覽器尚未完成CSSOM的構建和下載,但此時又想運行腳本,那么瀏覽器將延遲腳本執行和DOM構建,直到其完成CSSOM的下載和構建
復制代碼
也就是說,瀏覽器會先下載和構建CSSOM,然后再執行JavaScript ,最后再繼續構建DOM.
問題二、你真的了解回流和重繪嗎?
當網頁生成的時候,至少會渲染一次。在用戶訪問的過程中,還會不斷重新渲染,重新渲染會重復上圖中的第四部(回流)+ 第五步(重繪)或者只有第五步(重繪)。
1. 重繪:當render tree中的一些元素需要更新屬性,而這些屬性只是影響元素的外觀、風格,而不會影響布局的,比如background-color
2. 回流:當render tree中的一部分(或全部)因為元素的規模尺寸、布局、隱藏等改變而需要重新構建
復制代碼
回流必定會發生重繪,重繪不一定會引發回流
總結
以上是生活随笔為你收集整理的解析html网页原理,深入浅出浏览器渲染原理的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 温度压力测试软件什么好,温度压力测试
- 下一篇: LibreELEC(kodi)IPTV台