HTML渲染过程详解
由于本人對(duì)http協(xié)議以及dns對(duì)url的解析問題并不了解,所以這里之探討url請(qǐng)求加載到瀏覽器端時(shí),瀏覽器對(duì)html的解析到呈現(xiàn)過程,后來經(jīng)過幾位道友分享,整理了一下url解析的過程,如下:
用戶輸入url地址,瀏覽器根據(jù)域名尋找IP地址
瀏覽器向服務(wù)器發(fā)送http請(qǐng)求,如果服務(wù)器段返回以301之類的重定向,瀏覽器根據(jù)相應(yīng)頭中的location再次發(fā)送請(qǐng)求
服務(wù)器端接受請(qǐng)求,處理請(qǐng)求生成html代碼,返回給瀏覽器,這時(shí)的html頁面代碼可能是經(jīng)過壓縮的
瀏覽器接收服務(wù)器響應(yīng)結(jié)果,如果有壓縮則首先進(jìn)行解壓處理,緊接著就是頁面解析渲染
解析渲染該過程主要分為以下步驟:
解析與構(gòu)建DOM樹
前兩步我們放在一起討論,瀏覽器的實(shí)際工作也是將他們放在一起進(jìn)行的。對(duì)于HTML瀏覽器有專門的html解析器來解析HTML,并在解析的過程中構(gòu)建DOM樹。在這里我們討論兩種DOM元素的解析,即樣式(link、style)與腳本文件(script)。由于瀏覽器采用自上而下的方式解析,在遇到這兩種元素時(shí)都會(huì)阻塞瀏覽器的解析,直到外部資源加載并解析或執(zhí)行完畢后才會(huì)繼續(xù)向下解析html。對(duì)于樣式與腳本的先后順序同樣也會(huì)影響到瀏覽器的解析過程,究其原因主要在于:script腳本執(zhí)行過程中可能會(huì)修改html界面(如document.write函數(shù));DOM節(jié)點(diǎn)的CSS樣式會(huì)影響js的執(zhí)行結(jié)果。在我的測(cè)試中得到以下四條結(jié)論:
1)外部樣式會(huì)阻塞后續(xù)腳本執(zhí)行,直到外部樣式加載并解析完畢。
2)外部樣式不會(huì)阻塞后續(xù)外部腳本的加載,但會(huì)阻塞外部腳本的執(zhí)行。
從瀑布圖中我們可以看到,外部腳本與外部樣式是并行加載,但直到外部樣式加載完畢,外部腳本才開始執(zhí)行
3)如果后續(xù)外部腳本含有async屬性(IE下為defer),則外部樣式不會(huì)阻塞該腳本的加載與執(zhí)行
從瀑布圖中可以看到外部腳本的加載與執(zhí)行并不受link的阻塞
4)對(duì)于動(dòng)態(tài)創(chuàng)建的link標(biāo)簽不會(huì)阻塞其后動(dòng)態(tài)創(chuàng)建的script的加載與執(zhí)行,不管script標(biāo)簽是否具有async屬性,但對(duì)于其他非動(dòng)態(tài)創(chuàng)建的script,以上三條結(jié)論仍適用
這是最終頁面結(jié)構(gòu)
通過瀑布圖與頁面結(jié)果可以看到動(dòng)態(tài)創(chuàng)建的外部腳本并未受link的阻塞。
link或style標(biāo)簽都會(huì)被解析成DOM節(jié)點(diǎn)。瀏覽器對(duì)于樣式表還會(huì)生成CSSStyleSheet對(duì)象(C++代碼),他集成子CSSStyle,指標(biāo)是樣式表對(duì)象而不管該對(duì)象來自于Style還是link。該對(duì)象主要包含以下幾個(gè)重要屬性和方法
CSSRules 即css樣式代碼
type 表示樣式表類型的字符串。對(duì)CSS樣式表而言,這個(gè)字符串是“type/css”。
href 通過link生成的為樣式鏈接,否則為undefined
insertRule(rule,index):向cssRules集合中指定的位置插入rule字符串。IE不支持這個(gè)方法,但支持一個(gè)類似的addRule()方法。
deleteRule(index):刪除cssRules集合中指定的位置的規(guī)則。IE不支持這個(gè)方法,但支持一個(gè)類似的removeRule()方法。
文檔中對(duì)于所有的樣式表集合可以通過document.styleSheets來訪問。同時(shí)對(duì)于style或link DOM元素可以通過element.sheet來訪問CSSStyleSheet對(duì)象,IE中則通過element.styleSheet來訪問。
html解析完畢,DOM樹創(chuàng)建完成后DOMContentLoaded事件即觸發(fā),這時(shí)候可以用過script來操作DOM節(jié)點(diǎn)。
構(gòu)建呈現(xiàn)樹
HTML解析完畢后,開始構(gòu)建呈現(xiàn)樹RenderTree,這一步的主要工作在于將css樣式應(yīng)用到DOM節(jié)點(diǎn)上,WebKit內(nèi)核將這一過程稱為附著,其他瀏覽器有不同的概念。對(duì)前端工程師而言這個(gè)過程會(huì)涉及到CSS層疊問題。
首先將根據(jù)樣式重要性排序,由低到高依次為:
對(duì)于同一重要級(jí)別,則是根據(jù)CSS選擇符的特指度來判定優(yōu)先級(jí);一條樣式聲明的特指度由以下四個(gè)部分決定:S-I-C-E
- 聲明來自內(nèi)聯(lián)的style屬性則 S+1;
- 聲明中含有id屬性則 I+1;
- 聲明中含有類、偽類、屬性選擇器則 C+1;
- 生命中含有元素、偽元素選擇器則 E+1;
特指度的比較類似于兩個(gè)字符串之間比較大小。
呈現(xiàn)樹的每一個(gè)節(jié)點(diǎn)即為與其相對(duì)應(yīng)的DOM節(jié)點(diǎn)的CSS框,框的類型與DOM節(jié)點(diǎn)的display屬性有關(guān),block元素生成block框,inline元素生成inline框。每一個(gè)呈現(xiàn)樹節(jié)點(diǎn)都有與之相對(duì)應(yīng)的DOM節(jié)點(diǎn),但DOM節(jié)點(diǎn)不一定有與之相對(duì)應(yīng)的呈現(xiàn)樹節(jié)點(diǎn),比如display屬性為none的DOM節(jié)點(diǎn),而且呈現(xiàn)樹節(jié)點(diǎn)在呈現(xiàn)樹中的位置與他們?cè)贒OM樹中的位置不一定相同,比如float與絕對(duì)定位元素。
下圖為呈現(xiàn)樹與其相對(duì)應(yīng)的DOM樹節(jié)點(diǎn)
布局
呈現(xiàn)樹構(gòu)造完成后瀏覽器便進(jìn)行布局處理,及計(jì)算每個(gè)呈現(xiàn)樹節(jié)點(diǎn)的大小和位置信息。有道友可能要問,前面已將樣式附著到DOM節(jié)點(diǎn)上,不是已經(jīng)有了樣式信息為何還要計(jì)算大小。這里可以這樣理解,以上包含大小的樣式信息只是存在內(nèi)存里,并沒有實(shí)際使用,瀏覽器要根據(jù)窗口的實(shí)際大小來處理呈現(xiàn)樹節(jié)點(diǎn)的實(shí)際顯示大小和位置,比如對(duì)于margin為auto的處理。
布局是一個(gè)遞歸過程,從跟呈現(xiàn)節(jié)點(diǎn)開始,遞歸遍歷子節(jié)點(diǎn),計(jì)算集合幾何信息。具體過程還是比較復(fù)雜偶也不甚了解,道友們還是查閱其他資料吧。
繪制
布局完成后,便是將呈現(xiàn)樹繪制出來顯示在屏幕上。對(duì)于每一個(gè)呈現(xiàn)樹節(jié)點(diǎn)來說,主要繪制順序如下:
總結(jié)
以上是生活随笔為你收集整理的HTML渲染过程详解的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: ubuntu18使用wine安装TIM和
- 下一篇: vscode配置vue环境