目錄
一.瀏覽器渲染原理
二.渲染時(shí)間點(diǎn)
三.渲染流水線
1.解析html(Parse HTML)
1.1解析成DOM樹(document object model)
1.2解析成CSSOM樹(css?object model)
2.樣式計(jì)算(Recalculate Style)
3.布局(Layout)
4.分層(Layer)
5. 繪制(Paint)
6.分塊(Tiling)
7. 光柵化(Raster)
8. 畫(Draw)
四.附加面試題
1.什么是 reflow?
2.什么是 repaint?
3.為什么 transform 的效率高?
一.瀏覽器渲染原理
瀏覽器是如何渲染頁(yè)面的?
當(dāng)瀏覽器的網(wǎng)絡(luò)線程收到 HTML 文檔后,會(huì)產(chǎn)生一個(gè)渲染任務(wù),并將其傳遞給渲染主線程的消息隊(duì)列。
在事件循環(huán)機(jī)制的作用下,渲染主線程取出消息隊(duì)列中的渲染任務(wù),開啟渲染流程。
整個(gè)渲染流程分為多個(gè)階段,分別是: HTML 解析、樣式計(jì)算、布局、分層、繪制、分塊、光柵化、畫
每個(gè)階段都有明確的輸入輸出,上一個(gè)階段的輸出會(huì)成為下一個(gè)階段的輸入。
這樣,整個(gè)渲染流程就形成了一套組織嚴(yán)密的生產(chǎn)流水線。
二.渲染時(shí)間點(diǎn)
當(dāng)瀏覽器的網(wǎng)絡(luò)線程接收到HTML文檔后,會(huì)產(chǎn)生一個(gè)渲染任務(wù),并將其傳遞給消息隊(duì)列,在事件循環(huán)機(jī)制的作用下,渲染主線程(render thread)取出消息隊(duì)列中的渲染任務(wù),開啟渲染
三.渲染流水線
1.解析html(Parse HTML)
首先將html和css分別解析成DOM樹和CSSOM樹
1.1解析成DOM樹(document object model)
為什么要先解析成樹狀結(jié)構(gòu)內(nèi),因?yàn)镠TML文檔是很多雜亂的字符,為了更清楚它們之間的邏輯,更好地進(jìn)行后續(xù)的渲染步驟,瀏覽器先選擇將它們解析成更加清晰的邏輯結(jié)構(gòu)
1.2解析成CSSOM樹(css?object model)
解析過(guò)程中遇到 CSS 解析 CSS,遇到 JS 執(zhí)行 JS。為了提高解析效率,瀏覽器在開始解析前,會(huì)啟動(dòng)一個(gè)預(yù)解析的線程,率先下載 HTML 中的外部 CSS 文件和 外部的 JS 文件。
如果主線程解析到`link`位置,此時(shí)外部的 CSS 文件還沒(méi)有下載解析好,主線程不會(huì)等待,繼續(xù)解析后續(xù)的 HTML。這是因?yàn)橄螺d和解析 CSS 的工作是在預(yù)解析線程中進(jìn)行的。這就是 CSS 不會(huì)阻塞 HTML 解析的根本原因。
如果主線程解析到`script`位置,會(huì)停止解析 HTML,轉(zhuǎn)而等待 JS 文件下載好,并將全局代碼解析執(zhí)行完成后,才能繼續(xù)解析 HTML。這是因?yàn)?JS 代碼的執(zhí)行過(guò)程可能會(huì)修改當(dāng)前的 DOM 樹,所以 DOM 樹的生成必須暫停。這就是 JS 會(huì)阻塞 HTML 解析的根本原因。
第一步完成后,會(huì)得到 DOM 樹和 CSSOM 樹,瀏覽器的默認(rèn)樣式、內(nèi)部樣式、外部樣式、行內(nèi)樣式均會(huì)包含在 CSSOM 樹中。
2.樣式計(jì)算(Recalculate Style)
主線程會(huì)遍歷得到的 DOM 樹,依次為樹中的每個(gè)節(jié)點(diǎn)計(jì)算出它最終的樣式,稱之為 Computed Style。
在這一過(guò)程中,很多預(yù)設(shè)值會(huì)變成絕對(duì)值,比如`red`會(huì)變成`rgb(255,0,0)`;相對(duì)單位會(huì)變成絕對(duì)單位,比如`em`會(huì)變成`px`
這一步完成后,會(huì)得到一棵帶有樣式的 DOM 樹。
3.布局(Layout)
接下來(lái)是布局,布局完成后會(huì)得到布局樹。
布局階段會(huì)依次遍歷 DOM 樹的每一個(gè)節(jié)點(diǎn),計(jì)算每個(gè)節(jié)點(diǎn)的幾何信息。例如節(jié)點(diǎn)的寬高、相對(duì)包含塊的位置。
大部分時(shí)候,DOM 樹和布局樹并非一一對(duì)應(yīng)。
比如`display:none`的節(jié)點(diǎn)沒(méi)有幾何信息,因此不會(huì)生成到布局樹;又比如使用了偽元素選擇器,雖然 DOM 樹中不存在這些偽元素節(jié)點(diǎn),但它們擁有幾何信息,所以會(huì)生成到布局樹中。還有匿名行盒、匿名塊盒等等都會(huì)導(dǎo)致 DOM 樹和布局樹無(wú)法一一對(duì)應(yīng)。
4.分層(Layer)
下一步是分層
主線程會(huì)使用一套復(fù)雜的策略對(duì)整個(gè)布局樹中進(jìn)行分層。
分層的好處在于,將來(lái)某一個(gè)層改變后,僅會(huì)對(duì)該層進(jìn)行后續(xù)處理,從而提升效率。
滾動(dòng)條、堆疊上下文、transform、opacity 等樣式都會(huì)或多或少的影響分層結(jié)果,也可以通過(guò)`will-change`屬性更大程度的影響分層結(jié)果。
5. 繪制(Paint)
再下一步是繪制
主線程會(huì)為每個(gè)層單獨(dú)產(chǎn)生繪制指令集,用于描述這一層的內(nèi)容該如何畫出來(lái)。
渲染主線程的工作到這里就結(jié)束了,剩下的工作交給其他線程來(lái)完成
6.分塊(Tiling)
完成繪制后,主線程將每個(gè)圖層的繪制信息提交給合成線程,剩余工作將由合成線程完成。
合成線程首先對(duì)每個(gè)圖層進(jìn)行分塊,將其劃分為更多的小區(qū)域。
它會(huì)從線程池中拿取多個(gè)線程來(lái)完成分塊工作。
這是csdn網(wǎng)頁(yè)的分塊圖
分塊工程是交給多個(gè)線程同時(shí)進(jìn)行的
7. 光柵化(Raster)
分塊完成后,進(jìn)入光柵化階段。
優(yōu)先處理靠近視口的塊
合成線程會(huì)將塊信息交給 GPU 進(jìn)程,以極高的速度完成光柵化。
GPU 進(jìn)程會(huì)開啟多個(gè)線程來(lái)完成光柵化,并且優(yōu)先處理靠近視口區(qū)域的塊。
光柵化的結(jié)果,就是一塊一塊的位圖
8. 畫(Draw)
最后一個(gè)階段就是畫了
合成線程拿到每個(gè)層、每個(gè)塊的位圖后,生成一個(gè)個(gè)「指引(quad)」信息。
指引會(huì)標(biāo)識(shí)出每個(gè)位圖應(yīng)該畫到屏幕的哪個(gè)位置,以及會(huì)考慮到旋轉(zhuǎn)、縮放等變形。
變形發(fā)生在合成線程,與渲染主線程無(wú)關(guān),這就是`transform`效率高的本質(zhì)原因。
合成線程會(huì)把 quad 提交給 GPU 進(jìn)程,由 GPU 進(jìn)程產(chǎn)生系統(tǒng)調(diào)用,提交給 GPU 硬件,完成最終的屏幕成像。
四.附加面試題
1.什么是 reflow?
reflow 的本質(zhì)就是重新計(jì)算 layout 樹。
當(dāng)進(jìn)行了會(huì)影響布局樹的操作后,需要重新計(jì)算布局樹,會(huì)引發(fā) layout。
為了避免連續(xù)的多次操作導(dǎo)致布局樹反復(fù)計(jì)算,瀏覽器會(huì)合并這些操作,當(dāng) JS 代碼全部完成后再進(jìn)行統(tǒng)一計(jì)算。所以,改動(dòng)屬性造成的 reflow 是異步完成的。
也同樣因?yàn)槿绱?,?dāng) JS 獲取布局屬性時(shí),就可能造成無(wú)法獲取到最新的布局信息。
瀏覽器在反復(fù)權(quán)衡下,最終決定獲取屬性立即 reflow。
2.什么是 repaint?
repaint 的本質(zhì)就是重新根據(jù)分層信息計(jì)算了繪制指令。
當(dāng)改動(dòng)了可見樣式后,就需要重新計(jì)算,會(huì)引發(fā) repaint。
由于元素的布局信息也屬于可見樣式,所以 reflow 一定會(huì)引起 repaint。
3.為什么 transform 的效率高?
因?yàn)?transform 既不會(huì)影響布局也不會(huì)影響繪制指令,它影響的只是渲染流程的最后一個(gè)「draw」階段文章來(lái)源:http://www.zghlxwxcb.cn/news/detail-831720.html
由于 draw 階段在合成線程中,所以 transform 的變化幾乎不會(huì)影響渲染主線程。反之,渲染主線程無(wú)論如何忙碌,也不會(huì)影響 transform 的變化。文章來(lái)源地址http://www.zghlxwxcb.cn/news/detail-831720.html
到了這里,關(guān)于前端秘法進(jìn)階篇----這還是我們熟悉的瀏覽器嗎?(瀏覽器的渲染原理)的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!