瀏覽器渲染——(一)渲染過程

當(dāng)瀏覽器渲染一個(gè)html都發(fā)生了什么哮笆?

這個(gè)問題基本在面試的時(shí)候經(jīng)常會(huì)問到吧。經(jīng)常的回答是當(dāng)html 被加載到瀏覽器中霎俩,解析html構(gòu)建dom tree袭厂,通過link解析css,構(gòu)建render tree媳纬。把這倆個(gè)組合在一起双肤,渲染出看到的頁面施掏。(精簡的回答。)對(duì)的茅糜,但不全面七芭。本文進(jìn)行深度剖析。

一蔑赘,圖解流程


1狸驳,解析代碼。瀏覽器包含html解析器和css解析器缩赛。分別解析html和css代碼耙箍。html解析器會(huì)解析出dom,css解析器會(huì)解析出cssDom峦筒。cssDom的樣式映射都是全部計(jì)算過的究西,是個(gè)絕對(duì)值。我們?cè)诖a中寫的往往不是最終結(jié)果(元素可能繼承物喷,默認(rèn)卤材,calc等其他影響,瀏覽器不理解相對(duì)概念只會(huì)以絕對(duì)值展示)峦失。dom和cssDom都是樹型結(jié)構(gòu)扇丛。

2,合并樹尉辑,從Dom根結(jié)點(diǎn)開始遍歷每一個(gè)可見的節(jié)點(diǎn)帆精,為其找到適配的cssDom規(guī)則并應(yīng)用。將兩個(gè)樹合并成render tree 隧魄。a.某些節(jié)點(diǎn)不可見(如腳本標(biāo)簽<script>此類)b.某些節(jié)點(diǎn)被CSS隱藏了卓练,類似display:none。注意购啄,visibility:hidden此類屬于可見節(jié)點(diǎn)襟企,其仍然占據(jù)著布局空間。最終輸出的RenderTree將同時(shí)包含屏幕上的所有可見內(nèi)容及其樣式信息狮含。

3顽悼,layout,css提供了部分布局信息几迄,但瀏覽器想要的是元素相對(duì)于設(shè)備視窗內(nèi)的確切位置和大小蔚龙。僅僅靠render tree是不足以描述我們的頁面,我們?nèi)狈?jié)點(diǎn)之間確切的位置關(guān)系映胁。瀏覽器默認(rèn)通過文檔流進(jìn)行布局木羹,并通過css盒模型來描述每一個(gè)元素。所以我們可以輕易的捕獲元素在視窗內(nèi)的確切尺寸和大小屿愚,所有的相對(duì)測量值都會(huì)轉(zhuǎn)換成屏幕上的絕對(duì)像素汇跨。諸如float,flex之類的布局方式都需要重新計(jì)算务荆。布局信息會(huì)被存儲(chǔ)在一個(gè)與渲染樹相關(guān)聯(lián)的樹結(jié)構(gòu)里。layout階段結(jié)束后會(huì)輸出名為layoutTree的數(shù)據(jù)結(jié)構(gòu)穷遂。

4函匕,painting ,遍歷渲染樹蚪黑,進(jìn)行每個(gè)節(jié)點(diǎn)的繪制盅惜。

二,瀏覽器的進(jìn)程

對(duì)于進(jìn)程和線程的定義和理解請(qǐng)參考以下鏈接:

1忌穿,https://segmentfault.com/a/1190000012925872

2抒寂,http://imweb.io/topic/58e3bfa845e5c13468f567d5

以目前的Chrome為例,它采用的是多進(jìn)程架構(gòu)掠剑。不同的進(jìn)程有不同的功能屈芜。比如browser process主要負(fù)責(zé)瀏覽器界面顯示,與用戶交互朴译。包括地址欄井佑,書簽,后退和前進(jìn)按鈕等眠寿。頁面的渲染主要是在renderer process中進(jìn)行的躬翁。

1,Renderer process下的線程

a,主線程(main thread)

b盯拱,合成線程(COmpositor thread)

一般情況下盒发,諸如計(jì)算HTML 元素的 CSS 樣式,layout狡逢,paint和運(yùn)行JavaScript都運(yùn)行在主線程之中宁舰。我想你已經(jīng)注意到了,js的運(yùn)行也在主線程奢浑。這就是意味著明吩,樣式計(jì)算,layout殷费,paint和js的執(zhí)行是一種互斥關(guān)系。它們會(huì)互相阻塞低葫。如果正在計(jì)算布局详羡,那么js就無法及時(shí)的監(jiān)聽到事件。反過來嘿悬,js執(zhí)行占據(jù)了大量主線程時(shí)間实柠,你的layout和paint都會(huì)受到影響。

概覽

主線程:圖層的誕生

原有的layoutTree可以反映在二維平面上節(jié)點(diǎn)的相互關(guān)系善涨,但無法反映層次關(guān)系窒盐。


這是俯視角下的頁面


瀏覽器引入圖層概念來處理代碼中復(fù)雜的層次關(guān)系草则。(z-index,fixed等蟹漓,所以頁面關(guān)系可能不止一層)



這是一個(gè)demo

GraphicsLayer結(jié)束后還會(huì)轉(zhuǎn)換為cc layer炕横。但是樹的結(jié)構(gòu)不會(huì)再有更改∑狭#可以理解GraphicsLayer就是我們最終需要生成的圖層份殿。


這是一個(gè)demo

chrome會(huì)將它認(rèn)為是同一層坐標(biāo)體系下的layoutObject歸為一個(gè)Layer內(nèi)。

每一個(gè)LayoutObject都直接的或間接的與一個(gè)PaintLayer有關(guān)聯(lián)嗽交。那些共享同一坐標(biāo)空間的LayoutObject往往處在同一PaintLayer中卿嘲。如果沒有觸發(fā)上述條件,會(huì)和父元素共享一個(gè)坐標(biāo)空間夫壁。

特殊的dom胁澳,canvas浸策,video,根對(duì)象。特殊的css机蔗,css位置屬性,transform纽乱,透明度忿峻,filter等。


chrome會(huì)將它認(rèn)為是一層的paintLayer歸為一個(gè)GraphicsLayer內(nèi)撩扒。

事情并沒有結(jié)束似扔,chrome覺得目前的曾數(shù)量依然太多了。所以PaintLayer依然要繼續(xù)變形搓谆,繼續(xù)壓縮層的數(shù)量炒辉。由paintLayer轉(zhuǎn)化成graphicsLayer。那么什么是GraphicsLayer呢泉手?這里拋出一個(gè)可能大家都早已聽說過得概念:合成層黔寇。GraphicsLayer就是最終合成的候選人。

主線程:PAINT


到目前為止斩萌,我們?nèi)匀贿€在主線程中缝裤。我們剛剛這一系列l(wèi)ayer的轉(zhuǎn)換,都發(fā)生在layout和paint中間颊郎。當(dāng)我們滿心歡喜的拿到合成層時(shí)憋飞,是不是覺得快結(jié)束了,終于繪制了姆吭!很遺憾榛做,這個(gè)Paint可能和你想象中的階段不大一樣。


籠統(tǒng)的將三個(gè)階段解讀為一個(gè)Painting階段是不嚴(yán)謹(jǐn)?shù)模瑢?shí)際上Paint僅僅是其中第一個(gè)階段而已检眯。傳遞給Paint的是CC Layer厘擂。所以每一層都擁有獨(dú)立的Paint。每層都會(huì)擁有一個(gè)DisplayItem List來記錄該層所有的繪制操作锰瘸。注意刽严,只是記錄操作,沒有任何繪制行為的發(fā)生获茬。Displayitem list會(huì)與合成層綁定港庄,然后合成層被當(dāng)做主線程的最終輸出交給合成線程

合成線程:Commit


commit階段,主線程會(huì)提交一份cc layer的拷貝放入合成線程恕曲。隨后主線程便會(huì)進(jìn)入下一幀的渲染流程中鹏氧。兩個(gè)線程同步進(jìn)行,互不影響佩谣。commit階段雖然會(huì)短暫阻塞主線程把还,但是時(shí)間開銷很小。

合成線程:Tiling(鋪磚茸俭,蓋瓦的意思)


一個(gè)頁面的實(shí)際長度可能遠(yuǎn)遠(yuǎn)超過視窗大小吊履。將整個(gè)頁面每次都渲染出來是不明智的,因?yàn)橛脩粑幢卣娴臅?huì)瀏覽到視窗外的部分调鬓,這樣反而消耗了資源艇炎。除了縱橫向滾動(dòng)依次排列的磁貼,在存在zoom縮放操作時(shí)腾窝,也會(huì)根據(jù)每次縮放的情況來決定渲染哪些磁貼缀踪。所以在一些性能較差的手機(jī)上,對(duì)超長列表進(jìn)行快速滾動(dòng)虹脯,有時(shí)可以發(fā)現(xiàn)底部會(huì)有短暫白色的情況驴娃。這正是tiling階段動(dòng)態(tài)渲染的原因。

合成線程:Raster

主線程中paint階段生成的命令會(huì)在該階段執(zhí)行循集,將圖像壓進(jìn)位圖之中唇敞。位圖就是像素點(diǎn)陣圖。光柵化就是將圖像畫進(jìn)位圖的過程咒彤。之前我們?cè)趐aint存儲(chǔ)的繪制指令現(xiàn)在會(huì)拿出來執(zhí)行疆柔,以磁貼為單位。光柵化結(jié)束后這些位圖會(huì)上傳至GPU內(nèi)存之中镶柱。


合成線程:Activation


合成線程內(nèi)有兩棵樹婆硬。active樹在執(zhí)行完draw階段提交gpu線程繪制后,下一幀的pendingTree便可以繼續(xù)工作了奸例,不必等待畫面完全輸出至頁面上。一幀畫面只有真正activation之后變成active Tree才算進(jìn)入渲染流程。

合成線程:draw

draw階段仍然是對(duì)指令的包裝查吊。每個(gè)tile都會(huì)被“繪制”成“繪圖塊(draw quads)”谐区。每一個(gè)繪圖塊是一個(gè)在屏幕上指定位置繪制tile的指令。這個(gè)有點(diǎn)像我們?cè)谥骶€程Paint階段做得事逻卖。每一個(gè)塊都會(huì)包含對(duì)相應(yīng)tile在gpu內(nèi)存中的引用宋列。而所有繪圖塊會(huì)被包裝在一個(gè)CompositorFrame對(duì)象中。這個(gè)對(duì)象就是最終合成線程的終點(diǎn)评也,或者說炼杖,它就是整個(gè)renderer process的最終輸出。這個(gè)對(duì)象會(huì)被提交給browser process盗迟。



合成線程:display

Browser process會(huì)整合各個(gè)process提交的compositorFrame坤邪,讓gpu輸出真正的最終畫面。除了rederer process渲染的主頁面罚缕。plugin process也會(huì)影響畫面艇纺。那些我們常用的Chrome插件就是在這個(gè)階段與我們的頁面進(jìn)行整合的。


以上就是渲染的全部過程邮弹。當(dāng)然頁面也會(huì)因其他因素而改變黔衡。

1,用戶交互(包括滾動(dòng)腌乡,縮放盟劫,點(diǎn)擊等一系列操作)

2,js對(duì)dom的更新与纽。

用戶交互


js更新dom

JS對(duì)DOM的更新是需要謹(jǐn)慎的侣签,它往往會(huì)觸發(fā)從主線程到合成線程中的所有階段!

雖然聽起來很可怕渣锦,但是只要不是短期內(nèi)反復(fù)更新硝岗,現(xiàn)在的機(jī)器性能都足以應(yīng)對(duì)。但如果是一個(gè)無線循環(huán)動(dòng)畫之類的袋毙,就需要萬分謹(jǐn)慎了型檀。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市听盖,隨后出現(xiàn)的幾起案子胀溺,更是在濱河造成了極大的恐慌,老刑警劉巖皆看,帶你破解...
    沈念sama閱讀 219,039評(píng)論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件仓坞,死亡現(xiàn)場離奇詭異,居然都是意外死亡腰吟,警方通過查閱死者的電腦和手機(jī)无埃,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,426評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門徙瓶,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人嫉称,你說我怎么就攤上這事侦镇。” “怎么了织阅?”我有些...
    開封第一講書人閱讀 165,417評(píng)論 0 356
  • 文/不壞的土叔 我叫張陵壳繁,是天一觀的道長。 經(jīng)常有香客問我荔棉,道長闹炉,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,868評(píng)論 1 295
  • 正文 為了忘掉前任润樱,我火速辦了婚禮渣触,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘祥国。我一直安慰自己昵观,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,892評(píng)論 6 392
  • 文/花漫 我一把揭開白布舌稀。 她就那樣靜靜地躺著啊犬,像睡著了一般。 火紅的嫁衣襯著肌膚如雪壁查。 梳的紋絲不亂的頭發(fā)上觉至,一...
    開封第一講書人閱讀 51,692評(píng)論 1 305
  • 那天,我揣著相機(jī)與錄音睡腿,去河邊找鬼语御。 笑死,一個(gè)胖子當(dāng)著我的面吹牛席怪,可吹牛的內(nèi)容都是我干的应闯。 我是一名探鬼主播,決...
    沈念sama閱讀 40,416評(píng)論 3 419
  • 文/蒼蘭香墨 我猛地睜開眼挂捻,長吁一口氣:“原來是場噩夢啊……” “哼碉纺!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起刻撒,我...
    開封第一講書人閱讀 39,326評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤骨田,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后声怔,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體态贤,經(jīng)...
    沈念sama閱讀 45,782評(píng)論 1 316
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,957評(píng)論 3 337
  • 正文 我和宋清朗相戀三年醋火,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了悠汽。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片箱吕。...
    茶點(diǎn)故事閱讀 40,102評(píng)論 1 350
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖柿冲,靈堂內(nèi)的尸體忽然破棺而出殖氏,到底是詐尸還是另有隱情,我是刑警寧澤姻采,帶...
    沈念sama閱讀 35,790評(píng)論 5 346
  • 正文 年R本政府宣布,位于F島的核電站爵憎,受9級(jí)特大地震影響慨亲,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜宝鼓,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,442評(píng)論 3 331
  • 文/蒙蒙 一刑棵、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧愚铡,春花似錦蛉签、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,996評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至邑雅,卻和暖如春片橡,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背淮野。 一陣腳步聲響...
    開封第一講書人閱讀 33,113評(píng)論 1 272
  • 我被黑心中介騙來泰國打工捧书, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人骤星。 一個(gè)月前我還...
    沈念sama閱讀 48,332評(píng)論 3 373
  • 正文 我出身青樓经瓷,卻偏偏與公主長得像,于是被迫代替她去往敵國和親洞难。 傳聞我的和親對(duì)象是個(gè)殘疾皇子舆吮,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,044評(píng)論 2 355

推薦閱讀更多精彩內(nèi)容