前端学习(一) 浏览器渲染原理
前言
瀏覽器的內(nèi)核是指支持瀏覽器運(yùn)行的最核心的程序,分為兩個(gè)部分,一是渲染引擎,另一個(gè)是JS引擎,渲染引擎在不同的瀏覽器中也不是都相同的.目前市面上常見(jiàn)的瀏覽器內(nèi)核可以分為4種: Trident( IE ), Gecko( FireFox ), Blink( Chrome,Opera ), Webkit( Safari ),以 Webkit 為例,對(duì)現(xiàn)代瀏覽器的渲染過(guò)程進(jìn)行一個(gè)深度的剖析
頁(yè)面加載過(guò)程
簡(jiǎn)介要點(diǎn)如下:
- 瀏覽器根據(jù) DNS 服務(wù)器得到域名的 IP 地址
- 向這個(gè) IP 的機(jī)器發(fā)送 HTTP 請(qǐng)求
- 服務(wù)器收到,處理并返回 HTTP 請(qǐng)求
- 瀏覽器得到返回內(nèi)容
瀏覽器渲染過(guò)程
大體上分為如下三部分
瀏覽器會(huì)解析三個(gè)東西:
1.1 一是HTML/SVG/XHTML, HTML 字符串描述了一個(gè)頁(yè)面的結(jié)構(gòu),瀏覽器會(huì)把 HTML 結(jié)構(gòu)字符串解析轉(zhuǎn)換 DOM 樹(shù)形結(jié)構(gòu)
1.2 二是CSS,解析 CSS 會(huì)產(chǎn)生 CSS 規(guī)則樹(shù),它和 DOM 結(jié)構(gòu)比較像
1.3 三是 JavaScript 腳本,等到 JavaScript 腳本文件加載后, 通過(guò) DOM API 和 CSSOM API 來(lái)操作 DOM Tree 和 CSS Rule Tree
解析完成后,瀏覽器引擎會(huì)通過(guò) DOM Tree 和 CSS Rule Tree 來(lái)構(gòu)造 Rendering Tree
2.1 Rendering Tree 渲染樹(shù)并不等同于 DOM樹(shù),渲染樹(shù)只會(huì)包括需要顯示的節(jié)點(diǎn)和這些節(jié)點(diǎn)的樣式信息
2.2 CSS 的Rule Tree 主要是為了完成匹配并把 CSS Rule 附加上 Rrendering Tree 上的每個(gè) Element(也就是每個(gè) Frame)
2.3 然后,計(jì)算每個(gè) Frame 的位置,又叫做 layout 和 reflow 過(guò)程
最后通過(guò)調(diào)用操作系統(tǒng) Native GUI 的 API 繪制
構(gòu)建DOM
瀏覽器會(huì)遵循一套步驟將文件轉(zhuǎn)換為 DOM 樹(shù):
- 瀏覽器從磁盤(pán)或網(wǎng)絡(luò)讀取 HTML 的原始字節(jié),并根據(jù)文件的指定編碼將它們轉(zhuǎn)換成字符串
- 將字符串轉(zhuǎn)換為T(mén)oken,例如<html> <body>等. Token 中會(huì)標(biāo)志出當(dāng)前 Token 是"開(kāi)始標(biāo)簽"或是"結(jié)束標(biāo)簽"或"文本"等信息,以維護(hù)節(jié)點(diǎn)與節(jié)點(diǎn)間的關(guān)系
- 生成節(jié)點(diǎn)對(duì)象并構(gòu)建DOM.構(gòu)建 DOM 的過(guò)程中,不是等所有 Token 都轉(zhuǎn)換完成后再去生成節(jié)點(diǎn)對(duì)象,而是一邊生成 Token 一邊消耗 Token 來(lái)生成節(jié)點(diǎn)對(duì)象,即每個(gè)Token被生成后,會(huì)立刻消耗這個(gè) Token 創(chuàng)建出節(jié)點(diǎn)對(duì)象.帶有結(jié)束標(biāo)簽標(biāo)志的 Token 不會(huì)創(chuàng)建節(jié)點(diǎn)對(duì)象
假設(shè)有段 HTML 文本:
<html> <head><title>Web page parsing</title> </head> <body><div><h1>Web page parsing</h1><p>This is an example Web page.</p></div> </body> </html>上面這段HTML會(huì)解析成這樣:
構(gòu)建CSSOM
DOM 會(huì)捕獲頁(yè)面的內(nèi)容,但瀏覽器還需要知道頁(yè)面如何展示, 所以需要構(gòu)建CSSOM
構(gòu)建CSSOM的過(guò)程和構(gòu)建DOM的過(guò)程非常相似,當(dāng)瀏覽器接收到一段CSS,瀏覽器首先要做的是識(shí)別出Token,然后構(gòu)建節(jié)點(diǎn)并生成CSSOM
假設(shè)有這一段CSS:
在經(jīng)過(guò)一系列步驟后生成的CSSOM:
從圖中還可以看出.body節(jié)點(diǎn)的子節(jié)點(diǎn)繼承了 body 的樣式規(guī)則(font-size: 16px).這就是層疊規(guī)則以及CSS為什么叫CSS(層疊樣式表)
注意:CSS 匹配 HTML 元素是一個(gè)相當(dāng)復(fù)雜和有性能問(wèn)題的事情,所以,DOM樹(shù)要小,CSS要盡量用id和class,不要過(guò)度層疊下去
構(gòu)建渲染樹(shù)
生成 DOM 樹(shù)和 CSSOM 樹(shù)之后,就要將這兩棵樹(shù)組合為渲染樹(shù).
渲染樹(shù)只會(huì)包括需要顯示的節(jié)點(diǎn)和這些節(jié)點(diǎn)的樣式信息,如果某個(gè)節(jié)點(diǎn)是 display: none ,n那么就不會(huì)再渲染樹(shù)中顯示
渲染過(guò)程中,如果遇到 <script> 就停止渲染,執(zhí)行 JS 代碼.因?yàn)闉g覽器有 GUI 渲染線(xiàn)程與 JS 引擎線(xiàn)程,為了防止渲染出現(xiàn)不可預(yù)期的結(jié)果,這兩個(gè)線(xiàn)程是互斥的關(guān)系. JavaScript 的加載,解析與執(zhí)行會(huì)阻塞 DOM 的構(gòu)建,也就是說(shuō),在構(gòu)建 DOM 的時(shí)候,HTML 解析器若遇到了 JavaScript,就會(huì)暫停構(gòu)建 DOM,等到 JavaScript 加載完畢,瀏覽器再?gòu)闹袛嗟牡胤交謴?fù) DOM 構(gòu)建
JS 文件不只是阻塞 DOM 的構(gòu)建,它會(huì)導(dǎo)致 CSSOM 也阻塞 DOM 的構(gòu)建
因?yàn)镴avaScript不只是可以改 DOM,它還可以改 CSSOM.因?yàn)椴煌暾?CSSOM 是無(wú)法使用的,所以如果瀏覽器此時(shí)尚未完成 CSSOM 的下載和構(gòu)建,卻想要加載運(yùn)行腳本,那么瀏覽器將延遲腳本執(zhí)行和 DOM 構(gòu)建,直至其完成 CSSOM 的下載和構(gòu)建.也就是說(shuō), 在這種情況下,瀏覽器會(huì)先下載并構(gòu)建 CSSOM,再執(zhí)行JavaScript,最后再繼續(xù)構(gòu)建 DOM
因此,想首屏渲染的越快,就越不應(yīng)該在首屏就加載 JS 文件,這也是都建議將 script 標(biāo)簽放在 body 標(biāo)簽底部的原因.當(dāng)然在當(dāng)下,并不是說(shuō) script 標(biāo)簽必須放在底部,因?yàn)槟憧梢越o script 標(biāo)簽添加 defer 或者 async 屬性
總結(jié)
以上是生活随笔為你收集整理的前端学习(一) 浏览器渲染原理的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: oracle修改时间字段
- 下一篇: 【前端性能优化】浏览器渲染原理与性能优化