大家好利赋,我是李俊輝水评!如果您覺得文章有用,請幫忙點(diǎn)個贊或關(guān)注媚送,也為我鼓勵一下中燥,堅(jiān)持寫下去!
本文是轉(zhuǎn)載塘偎,是目前為止看到對瀏覽器渲染過程描述最清晰的文章褪那,故原文不動轉(zhuǎn)載過來幽纷,只修復(fù)了一點(diǎn)小瑕疵式塌!
webkit渲染引擎流程
關(guān)鍵渲染路徑
關(guān)鍵渲染路徑是指瀏覽器從最初接收請求來的HTML博敬、CSS、javascript等資源峰尝,然后解析偏窝、構(gòu)建樹、渲染布局武学、繪制祭往,最后呈現(xiàn)給客戶能看到的界面這整個過程
瀏覽器請求、加載火窒、渲染一個頁面的耗時任務(wù)主要有:
①DNS 解析查詢
②TCP/IP 連接
③HTTP 請求和響應(yīng)
④服務(wù)器響應(yīng)
⑤客戶端渲染
客戶端渲染也就是我們說的瀏覽器渲染硼补,主要包括以下幾步:
①解析HTML生成DOM樹
②解析CSS生成CSSOM規(guī)則樹
③將DOM樹與CSSOM規(guī)則樹合并在一起生成渲染樹
④遍歷渲染樹開始布局,計(jì)算每個節(jié)點(diǎn)的位置大小信息
⑤將渲染樹每個節(jié)點(diǎn)繪制到屏幕
注:上面步驟不一定是一次性順序完成熏矿。如果 DOM 或 CSSOM 被修改已骇,以上過程需要重復(fù)執(zhí)行,這樣才能計(jì)算出哪些像素需要在屏幕上進(jìn)行重新渲染票编。
構(gòu)建DOM樹
當(dāng)瀏覽器接收到服務(wù)器響應(yīng)來的HTML文檔后褪储,會遍歷文檔節(jié)點(diǎn),HTML Parser將HTML標(biāo)記解析成DOM Tree
但DOM樹的生成過程中可能會被CSS和JS的加載執(zhí)行阻塞,后面講解
例1:
<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>
經(jīng)過解析之后的DOM Tree差不多就是:
構(gòu)建CSSOM規(guī)則樹
CSS Parse將每個CSS文件都被解析成一個StyleSheet對象慧域,每個對象都包含Style Rules鲤竹,Style Rules也叫CSSOM(CSS Object Model)。
例2:
阻塞渲染
當(dāng)HTML解析器(HTML Parser)遇到script標(biāo)記阻塞時昔榴,解析器雖然會停止構(gòu)建 DOM辛藻,但仍會執(zhí)行JavaScript腳本的資源直至腳本執(zhí)行完再開始構(gòu)建DOM;如果JavaScript腳本還操作了CSS互订,而正好這個CSSOM還沒有下載和構(gòu)建吱肌,這時就存在阻塞的資源,瀏覽器會延遲JavaScript腳本執(zhí)行屁奏,直至完成其CSSOM的下載和構(gòu)建再執(zhí)行岩榆。
①遵循下面兩個原則
CSS 優(yōu)先:引入順序上,CSS 資源先于 JavaScript 資源
JavaScript 置后:我們通常把JS代碼放到頁面底部坟瓢,且JavaScript 應(yīng)盡量少影響 DOM 的構(gòu)建
②使用媒體類型(media type)和媒體查詢(media query)
<link href="vue.css" rel="stylesheet" media="print"> //設(shè)置了媒體類型勇边,會加載但不會阻塞
<link href="vue.css" rel="stylesheet" media="(min-width: 30em) and (orientation: landscape)">
//提供了媒體查詢,會在符合條件時阻塞渲染
③使用defer或者async(這2個屬性只對設(shè)置了scr屬性的外部腳本有效折联,對內(nèi)聯(lián)腳本(沒有設(shè)置src屬性的script)無效)
關(guān)于JavaScript的加載執(zhí)行順序
<script src="vue.js" defer></script>
//defer的script將會并發(fā)異步的去下載對應(yīng)的外部腳本文件(可能從本地緩存中獲取)
vue.js下載完成后不會馬上執(zhí)行粒褒,要等到HTML解析完成后,按腳本出現(xiàn)的順序依次執(zhí)行诚镰,這個過程中多個腳本之間是順序執(zhí)行
(即延遲執(zhí)行引入的js腳本)
<script src="vue.js" async></script>
//async的script將會并發(fā)異步的去下載對應(yīng)的外部腳本文件(可能從本地緩存中獲绒确亍)祥款,
vue.js下載完成后,渲染引擎中斷渲染月杉,執(zhí)行這個腳本以后刃跛,再繼續(xù)渲染,這個過程中多個腳本按下載完成的時間的先后順序依次執(zhí)行
構(gòu)建渲染樹
Render Tree的構(gòu)建其實(shí)就是DOM Tree和CSSOM Attach的過程(每個 DOM 節(jié)點(diǎn)都有一個“attach”方法)
樣式計(jì)算:
樣式計(jì)算是個很復(fù)雜的問題苛萎。DOM中的每個節(jié)點(diǎn)可以對應(yīng)樣式表中的多個元素桨昙,樣式表包括了所有樣式:瀏覽器默認(rèn)樣式表,自定義樣式表腌歉,inline樣式元素蛙酪,HTML可視化屬性如:width=100
注:display等于none的不會被顯示在渲染樹里,但是visibility等于hidden的元素是會顯示在渲染樹里的
渲染樹布局(Layout)
創(chuàng)建渲染樹后翘盖,下一步就是布局(Layout),或者叫回流(reflow)桂塞,這個過程就是通過渲染樹中渲染對象的信息,計(jì)算出每一個渲染對象的位置和尺寸馍驯,將其安置在瀏覽器窗口的正確位置阁危,而有些時候我們會在文檔布局完成后對DOM進(jìn)行修改,這時候可能需要重新進(jìn)行布局泥彤,也可稱其為回流欲芹,本質(zhì)上還是一個布局的過程,每一個渲染對象都有一個布局或者回流方法吟吝,實(shí)現(xiàn)其布局或回流菱父。
渲染樹繪制(Painting)
在繪制階段,系統(tǒng)會遍歷渲染樹剑逃,并調(diào)用渲染器的“paint”方法浙宜,將渲染器的內(nèi)容顯示在屏幕上。繪制工作是使用用戶界面基礎(chǔ)組件完成的蛹磺。
reflow(重排)和repaint(重繪):
repaint:屏幕的一部分重畫粟瞬,不影響整體布局,比如某個CSS的背景色變了萤捆,但元素的幾何尺寸和位置不變
常見引起重繪(repaint)屬性和方法:
reflow:元件的幾何尺寸變了裙品,我們需要重新驗(yàn)證并計(jì)算Render Tree,是Render Tree的一部分或全部發(fā)生了變化俗或。這就是reflow(Layout),reflow 會從這個root frame開始遞歸往下市怎,依次計(jì)算所有的結(jié)點(diǎn)幾何尺寸和位置,在reflow過程中辛慰,可能會增加一些frame区匠。
常見引起回流(reflow)屬性和方法:
注: display:none會觸發(fā)reflow,visibility: hidden只會觸發(fā)replaint帅腌;reflow的成本比replaint的成本高得多的多驰弄。DOM Tree里的每個結(jié)點(diǎn)都會有reflow方法麻汰,一個結(jié)點(diǎn)的reflow很有可能導(dǎo)致子結(jié)點(diǎn),甚至父點(diǎn)以及同級結(jié)點(diǎn)的reflow戚篙。
$('body').css('color', 'red'); // repaint
$('body').css('margin', '2px'); // reflow, repaint
var bstyle = document.body.style; // cache
bstyle.padding = "20px"; // reflow, repaint
bstyle.border = "10px solid red"; // 再一次的 reflow 和 repaint
bstyle.color = "blue"; // repaint
bstyle.backgroundColor = "#fad"; // repaint
bstyle.fontSize = "2em"; // reflow, repaint
document.body.appendChild(document.createTextNode('dude!'));// new DOM element - reflow, repaint
N弼辍!已球!瀏覽器不會像上面那樣臣镣,每改一次樣式,它就reflow或repaint一次智亮。一般來說,瀏覽器會把這樣的操作積攢一批点待,然后做一次reflow阔蛉,這又叫異步reflow或增量異步reflow。但是有些情況瀏覽器是不會這么做的癞埠,比如:resize(調(diào)整)窗口状原,改變了頁面默認(rèn)的字體等這些操作,瀏覽器會馬上進(jìn)行reflow苗踪。
總結(jié)
了解瀏覽器渲染機(jī)制的原理和過程颠区,可以優(yōu)化css樣式來提升瀏覽器渲染時的一些性能問題
如果您覺得文章有用,請幫忙點(diǎn)個贊或關(guān)注通铲,也為我鼓勵一下毕莱,堅(jiān)持寫下去,在此感謝??颅夺!
轉(zhuǎn)載一定注明出處朋截!
本文地址:http://www.reibang.com/p/b968f18150fe
2020年2月12日 新冠狀病毒期間憋在家
原文鏈接:https://blog.csdn.net/liujianfeng1214/article/details/86690284