Warning: error_log(/data/www/wwwroot/hmttv.cn/caches/error_log.php): failed to open stream: Permission denied in /data/www/wwwroot/hmttv.cn/phpcms/libs/functions/global.func.php on line 537 Warning: error_log(/data/www/wwwroot/hmttv.cn/caches/error_log.php): failed to open stream: Permission denied in /data/www/wwwroot/hmttv.cn/phpcms/libs/functions/global.func.php on line 537
者簡(jiǎn)介:高揚(yáng),來(lái)自抖音社區(qū)安全前端團(tuán)隊(duì),團(tuán)隊(duì)負(fù)責(zé)的工作重點(diǎn)在于降低社區(qū)中不良內(nèi)容與行為對(duì)用戶造成的傷害。
觀察瀏覽器的任務(wù)管理器可以發(fā)現(xiàn),打開(kāi)瀏覽器的一個(gè)頁(yè)面需要多個(gè)進(jìn)程,包括瀏覽器進(jìn)程、GPU進(jìn)程、網(wǎng)絡(luò)進(jìn)程、渲染進(jìn)程等,有插件的話還會(huì)包括各種插件進(jìn)程(Chrome選項(xiàng) -> 更多工具 -> 任務(wù)管理器)。
本文將聚焦于瀏覽器的各個(gè)進(jìn)程間是如何配合,將頁(yè)面呈現(xiàn)給用戶的。
你將了解到
進(jìn)程和線程
單進(jìn)程和多進(jìn)程瀏覽器
單進(jìn)程瀏覽器
單進(jìn)程瀏覽器是指所有功能模塊(網(wǎng)絡(luò)、插件、JS運(yùn)行環(huán)境、渲染引擎、頁(yè)面等)都運(yùn)行在同一進(jìn)程中的瀏覽器(早期的IE、Firefox)。
單進(jìn)程瀏覽器存在的問(wèn)題:
多進(jìn)程瀏覽器
Chrome一問(wèn)世便使用了多進(jìn)程的架構(gòu),其頁(yè)面運(yùn)行在了單獨(dú)的渲染進(jìn)程中,插件運(yùn)行在單獨(dú)的插件進(jìn)行中,進(jìn)程間使用IPC進(jìn)行通信。
瀏覽器的主要進(jìn)程有哪些:
默認(rèn)情況下,Chrome 會(huì)為每個(gè) Tab 標(biāo)簽創(chuàng)建一個(gè)渲染進(jìn)程。因?yàn)殇秩具M(jìn)程所有的內(nèi)容都是通過(guò)網(wǎng)絡(luò)獲取的,會(huì)存在一些惡意代碼利用瀏覽器漏洞對(duì)系統(tǒng)進(jìn)行攻擊,所以運(yùn)行在渲染進(jìn)程里面的代碼是不被信任的。這也是為什么 Chrome 會(huì)讓渲染進(jìn)程運(yùn)行在安全沙箱里,就是為了保證系統(tǒng)的安全。
其實(shí),Chrome 剛開(kāi)始發(fā)布的時(shí)候是沒(méi)有單獨(dú) GPU 進(jìn)程的,都是放到瀏覽器主進(jìn)程中的。而 GPU 的使用初衷是為了實(shí)現(xiàn) 3D CSS 的效果,只是隨后網(wǎng)頁(yè)、Chrome 的 UI 界面都選擇采用 GPU 來(lái)繪制,這使得 GPU 成為瀏覽器普遍的需求。最后,Chrome 在其多進(jìn)程架構(gòu)上也引入了 GPU 進(jìn)程。
多進(jìn)程瀏覽器是如何解決單進(jìn)程瀏覽的問(wèn)題的:
多進(jìn)程瀏覽器存在的問(wèn)題:
從用戶發(fā)出URL請(qǐng)求到頁(yè)面開(kāi)始解析的過(guò)程,叫做導(dǎo)航,是網(wǎng)絡(luò)加載流程和渲染流程之間的橋梁。
渲染流水線
渲染流水線可分為如下幾個(gè)子階段:構(gòu)建 DOM 樹(shù)、樣式計(jì)算、布局、分層、繪制、分塊、光柵化和合成。
注意,并非布局樹(shù)的每個(gè)節(jié)點(diǎn)都包含一個(gè)圖層,一個(gè)節(jié)點(diǎn)可以直接或間接地屬于一個(gè)層,例如一個(gè)節(jié)點(diǎn)可以從屬于父節(jié)點(diǎn)的圖層
基于上述瀏覽器的渲染原理,我們可以理解回流和重繪是如何對(duì)瀏覽器性能造成影響的。由于瀏覽器渲染頁(yè)面默認(rèn)使用流式布局模型,當(dāng)某個(gè)DOM或CSS幾何屬性發(fā)生改變后,文檔流就會(huì)受到波動(dòng),就需要對(duì)DOM重新進(jìn)行計(jì)算,重新布局頁(yè)面,引發(fā)回流。
[1] 瀏覽器工作原理與實(shí)踐:https://time.geekbang.org/column/intro/100033601
[2] 瀏覽器進(jìn)程架構(gòu)的演化:https://zhuanlan.zhihu.com/p/96957235
覽器渲染頁(yè)面有以下幾個(gè)步驟:
載網(wǎng)絡(luò),侵權(quán)必刪
我們可能都知道瀏覽器含有一個(gè)渲染引擎,用來(lái)渲染窗口所展示的內(nèi)容。默認(rèn)情況下,渲染引擎可以顯示html、xml文檔及圖片,它也可以借助插件(一種瀏覽器擴(kuò)展)顯示其他類(lèi)型數(shù)據(jù),例如使用PDF閱讀器插件,用于顯示PDF格式。但是其具體的渲染原理和流程估計(jì)也有很多人都不知道或者不清楚吧。這些天研究了一下瀏覽器的渲染原理,有了些心得,在這里跟大家分享一下,這里只討論渲染引擎最主要的用途——顯示應(yīng)用了CSS之后的html及圖片。
渲染引擎簡(jiǎn)介
本文所討論的瀏覽器——Firefox、Chrome和Safari是基于兩種渲染引擎構(gòu)建的,F(xiàn)irefox使用Geoko——Mozilla自主研發(fā)的渲染引擎,Safari和Chrome都使用webkit。
渲染主流程
渲染引擎首先通過(guò)網(wǎng)絡(luò)獲得所請(qǐng)求文檔的內(nèi)容,通常以8K分塊的方式完成。下面是渲染引擎在取得內(nèi)容之后的基本流程:
解析html以構(gòu)建dom樹(shù) -> 構(gòu)建render樹(shù) -> 布局render樹(shù) -> 繪制render樹(shù)
這里先解釋一下幾個(gè)概念,方便大家理解:
DOM Tree:瀏覽器將HTML解析成樹(shù)形的數(shù)據(jù)結(jié)構(gòu)。
CSS Rule Tree:瀏覽器將CSS解析成樹(shù)形的數(shù)據(jù)結(jié)構(gòu)。
Render Tree: DOM和CSSOM合并后生成Render Tree。
layout: 有了Render Tree,瀏覽器已經(jīng)能知道網(wǎng)頁(yè)中有哪些節(jié)點(diǎn)、各個(gè)節(jié)點(diǎn)的CSS定義以及他們的從屬關(guān)系,從而去計(jì)算出每個(gè)節(jié)點(diǎn)在屏幕中的位置。
painting: 按照算出來(lái)的規(guī)則,通過(guò)顯卡,把內(nèi)容畫(huà)到屏幕上。
reflow(回流):當(dāng)瀏覽器發(fā)現(xiàn)某個(gè)部分發(fā)生了點(diǎn)變化影響了布局,需要倒回去重新渲染,內(nèi)行稱(chēng)這個(gè)回退的過(guò)程叫 reflow。reflow 會(huì)從 <html> 這個(gè) root frame 開(kāi)始遞歸往下,依次計(jì)算所有的結(jié)點(diǎn)幾何尺寸和位置。reflow 幾乎是無(wú)法避免的。現(xiàn)在界面上流行的一些效果,比如樹(shù)狀目錄的折疊、展開(kāi)(實(shí)質(zhì)上是元素的顯 示與隱藏)等,都將引起瀏覽器的 reflow。鼠標(biāo)滑過(guò)、點(diǎn)擊……只要這些行為引起了頁(yè)面上某些元素的占位面積、定位方式、邊距等屬性的變化,都會(huì)引起它內(nèi)部、周?chē)踔琳麄€(gè)頁(yè)面的重新渲 染。通常我們都無(wú)法預(yù)估瀏覽器到底會(huì) reflow 哪一部分的代碼,它們都彼此相互影響著。
repaint(重繪):改變某個(gè)元素的背景色、文字顏色、邊框顏色等等不影響它周?chē)騼?nèi)部布局的屬性時(shí),屏幕的一部分要重畫(huà),但是元素的幾何尺寸沒(méi)有變。
注意:(1)display:none 的節(jié)點(diǎn)不會(huì)被加入Render Tree,而visibility: hidden 則會(huì),所以,如果某個(gè)節(jié)點(diǎn)最開(kāi)始是不顯示的,設(shè)為display:none是更優(yōu)的。
(2)display:none 會(huì)觸發(fā) reflow,而 visibility:hidden 只會(huì)觸發(fā) repaint,因?yàn)闆](méi)有發(fā)現(xiàn)位置變化。
(3)有些情況下,比如修改了元素的樣式,瀏覽器并不會(huì)立刻reflow 或 repaint 一次,而是會(huì)把這樣的操作積攢一批,然后做一次 reflow,這又叫異步 reflow 或增量異步 reflow。但是在有些情況下,比如resize 窗口,改變了頁(yè)面默認(rèn)的字體等。對(duì)于這些操作,瀏覽器會(huì)馬上進(jìn)行 reflow。
來(lái)看看webkit的主要流程:
再來(lái)看看Geoko的主要流程:
Gecko 里把格式化好的可視元素稱(chēng)做“幀樹(shù)”(Frame tree)。每個(gè)元素就是一個(gè)幀(frame)。 webkit 則使用”渲染樹(shù)”這個(gè)術(shù)語(yǔ),渲染樹(shù)由”渲染對(duì)象”組成。webkit 里使用”layout”表示元素的布局,Gecko則稱(chēng)為”reflow”。Webkit使用”Attachment”來(lái)連接DOM節(jié)點(diǎn)與可視化信息以構(gòu)建渲染樹(shù)。一個(gè)非語(yǔ)義上的小差別是Gecko在HTML與DOM樹(shù)之間有一個(gè)附加的層 ,稱(chēng)作”content sink”,是創(chuàng)建DOM對(duì)象的工廠。
盡管Webkit與Gecko使用略微不同的術(shù)語(yǔ),這個(gè)過(guò)程還是基本相同的,如下:
1. 瀏覽器會(huì)將HTML解析成一個(gè)DOM樹(shù),DOM 樹(shù)的構(gòu)建過(guò)程是一個(gè)深度遍歷過(guò)程:當(dāng)前節(jié)點(diǎn)的所有子節(jié)點(diǎn)都構(gòu)建好后才會(huì)去構(gòu)建當(dāng)前節(jié)點(diǎn)的下一個(gè)兄弟節(jié)點(diǎn)。
2. 將CSS解析成 CSS Rule Tree 。
3. 根據(jù)DOM樹(shù)和CSSOM來(lái)構(gòu)造 Rendering Tree。注意:Rendering Tree 渲染樹(shù)并不等同于 DOM 樹(shù),因?yàn)橐恍┫馠eader或display:none的東西就沒(méi)必要放在渲染樹(shù)中了。
4. 有了Render Tree,瀏覽器已經(jīng)能知道網(wǎng)頁(yè)中有哪些節(jié)點(diǎn)、各個(gè)節(jié)點(diǎn)的CSS定義以及他們的從屬關(guān)系。下一步操作稱(chēng)之為layout,顧名思義就是計(jì)算出每個(gè)節(jié)點(diǎn)在屏幕中的位置。
5. 再下一步就是繪制,即遍歷render樹(shù),并使用UI后端層繪制每個(gè)節(jié)點(diǎn)。
注意:上述這個(gè)過(guò)程是逐步完成的,為了更好的用戶體驗(yàn),渲染引擎將會(huì)盡可能早的將內(nèi)容呈現(xiàn)到屏幕上,并不會(huì)等到所有的html都解析完成之后再去構(gòu)建和布局render樹(shù)。它是解析完一部分內(nèi)容就顯示一部分內(nèi)容,同時(shí),可能還在通過(guò)網(wǎng)絡(luò)下載其余內(nèi)容。
*請(qǐng)認(rèn)真填寫(xiě)需求信息,我們會(huì)在24小時(shí)內(nèi)與您取得聯(lián)系。