【譯】深入了解現(xiàn)代web瀏覽器(三)渲染進程內部工作

渲染進程的內部工作

這是我們了解瀏覽器如何工作4篇博客的第3篇。之前奸柬,我們介紹了 多進程架構 和 導航流程鹉梨。在本文中,我們將研究渲染進程內部發(fā)生了什么序攘。

渲染器進程涉及web優(yōu)化的許多方面茴她。由于渲染進程內部發(fā)生了很多事情,因此本文只是概述程奠。如果你想更加深入丈牢,“web基礎知識的性能優(yōu)化部分”有更多的資源。

渲染進程處理web內容

渲染進程負責處理tab選項卡內發(fā)生的所有事情瞄沙。在一個渲染進程中己沛,主進程處理你發(fā)送給用戶的大多數(shù)代碼慌核。如果有時候你使用web worker 或者 service worker,你的部分 javascript 由woker線程處理申尼。排版和光柵線程也在渲染進程內部運行垮卓,以便高效,流暢的渲染頁面师幕。

渲染進程的核心工作是將html粟按、css和javascript轉換為可以與用戶交互的web頁面。

renderer.png
renderer.png

解析

DOM構造

當渲染進程接收到導航提交的信息霹粥,并且開始接收html數(shù)據(jù)灭将,主線程開始解析文本字符(html),并且將其轉換為文檔對象模型(DOM)后控。

DOM是一個瀏覽器對頁面的內部表示庙曙,也是web開發(fā)者可以通過javascript與之交互的數(shù)據(jù)結構和API。

解析一個HTML文檔到DOM是通過HTML標準來定義的浩淘。你可能注意到將HTML放到瀏覽器從來沒有拋出過錯誤捌朴。例如,缺少閉合 **</p> **是一個合法的HTML张抄。錯誤的標記例如 **Hi! <b>I'm <i>Chrome</b>!</i> **(b標簽在i標簽之前關閉)男旗,它被看成是 Hi! <b>I'm <i>Chrome</i></b><i>!</i>。這是因為HTML規(guī)范定義了如何優(yōu)雅的處理這些錯誤欣鳖。如果你關心這些事情是如何完成的,你可以閱讀HTML規(guī)范中“錯誤處理和解析中奇怪的例子”一節(jié)茴厉。

子資源加載

一個網(wǎng)站通常會使用額外的資源泽台,例如圖片、css和javascript矾缓。這些文件需要從網(wǎng)絡或者緩存中加載怀酷。主進程可以 在解析構建DOM的時候一個接一個的請求他們,但為了加快速度嗜闻,“預加載掃描”會同時運行蜕依。如果在HTML里面有一些像img和link的內容,預加載會查看HTML解析生成的token琉雳,并且在瀏覽器進程中發(fā)送網(wǎng)絡請求样眠。

dom.png
dom.png

javascript會阻塞解析

當HTML解析發(fā)現(xiàn)一個script標簽,它停止解析HTML文檔翠肘,并且去加載檐束,解析,并且執(zhí)行javascript代碼束倍。為什么被丧?因為javascript可以改變文檔的形狀盟戏,使用document.write()可以改變整個的DOM結構(解析模型概述在HTML定義里有一個好的繪圖)。這是HTML解析為什么在恢復HTML文檔解析之前等待javascript執(zhí)行甥桂。如果你像深入了解javascript執(zhí)行發(fā)生了什么柿究,V8團隊關于此的討論在這。

提示瀏覽器如何加載資源

web開發(fā)者有很多種方式可以發(fā)送提示給瀏覽器按序加載資源黄选。如果你的javascript沒有使用document.write()蝇摸,你可以添加 async 和 defer 屬性給 <script> 標簽。瀏覽器可以異步地加載和執(zhí)行 javascript 代碼糕簿,并且不會阻塞html解析探入。如果適合的話你可能也會使用 javascript module。<link rel="preload">是一種通知瀏覽器在當前導航需要盡可能早的下載資源的方式懂诗。你可以閱讀更多的內容在這里 Resource Prioritization – Getting the Browser to Help You.

樣式計算

只有一個DOM是不足以知道頁面長什么樣子的蜂嗽,因為我們可以在css中設置頁面樣式。主線程解析CSS并且為每個DOM節(jié)點準確地計算出樣式殃恒。這是基于CSS選擇器為每個元素應用對應樣式的信息植旧。你可以在 DevTools 中的 computed 部分看到這些信息。

computedstyle.png
computedstyle.png

即使你沒有提供任何的CSS离唐,每個DOM節(jié)點也會又一個computed樣式病附。<h1>標簽比<h2>標簽展示出來大,并且為每個元素都定義了外間距亥鬓。這是因為瀏覽器有一個默認樣式表完沪。如果你想知道chrome有哪些默認的css,請查看這個chrome默認css嵌戈。

布局

現(xiàn)在渲染進程知道文檔的結構和每個節(jié)點的樣式覆积,但是這些還不足以渲染一個頁面。想象一下你在電話里面為你的朋友描述一副畫熟呛】淼担“這里有一個大紅色的圓和一個小的藍色正方形”這些信息不能夠讓你的朋友準確的知道畫到底是什么樣子。

tellgame.png
tellgame.png

布局是一個尋找元素坐標的過程庵朝。主線程遍歷DOM和計算樣式吗冤,創(chuàng)建包含x,y坐標和邊界框大小的布局樹九府。布局樹和DOM樹有著相似的結構椎瘟,但是它僅僅包含頁面上可見元素的關聯(lián)信息。如果應用了 display:none侄旬,那么這個元素就不是布局樹的一部分(然而降传,一個visibility:hidden的元素在布局樹中)。類似地勾怒,一個包含內容的偽類就像p::before{content: "Hi!"}被應用婆排,它會包含在布局樹中声旺,即使它不在DOM中。

layout.png
layout.png

確定頁面布局是一個有挑戰(zhàn)的任務段只。即使最簡單的頁面腮猖,從上到下塊布局,也必須去考慮字體多大赞枕,哪里需要換行澈缺,因為這些都會影響段落的大小和形狀;而且也會影響下一行的段落的內容炕婶。

CSS可以使元素浮動到一邊姐赡,屏蔽溢出項,改變書寫的方向柠掂。你可以想象项滑,這個布局階段有一個艱巨的任務。在Chrome中涯贞,一個工程師團隊都在為布局工作枪狂。如果你想了解更多他們的工作細節(jié),請點擊 演講視頻 觀看有趣的記錄宋渔。

繪制

有了DOM州疾,樣式,布局還是不足以渲染一個頁面皇拣。假設你想模仿一幅畫严蓖。你知道大小,形狀氧急,元素的位置谈飒,但是你仍然需要判斷繪制的順序。

drawgame.png
drawgame.png

例如态蒂,會為一些元素設置z-index,在下面的例子中费什,按照HTML的順序繪制將會出現(xiàn)錯誤的渲染結果钾恢。

zindex.png
zindex.png

圖8:頁面元素按照HTML標記的順序出現(xiàn),由于未考慮 z-index導致生成錯誤的渲染圖

在當前繪制步驟鸳址,主線程遍歷布局樹去生成繪制記錄瘩蚪。繪制記錄是對繪制過程的記錄,例如“先背景稿黍,后文字疹瘦,最后矩形”。如果你使用 javascript 在<canvas>元素上繪制巡球,這個過程對你就比較熟悉言沐。


paint.png
paint.png

圖9:主線程遍歷布局樹并且生成繪制記錄

更新渲染流非常昂貴

在渲染流中要掌握的最重要的一點是邓嘹,在每一步中,使用上一步操作的結果去生成新數(shù)據(jù)险胰。例如汹押,如果布局樹中的某些發(fā)生改變,需要為受影響的文檔部分重新生成繪制順序起便。

如果為某些元素設置動畫棚贾,瀏覽器必須在每個frame中間去運行這些操作。我們大多數(shù)的顯示器都是每秒鐘刷新60次屏幕榆综;當你在每一幀中在屏幕上移動物體時妙痹,動畫對于人眼的顯示都是平滑的。然而鼻疮,如果錯過了它們之間的幀怯伊,則頁面將顯示為“混亂”。


pagejank1.png
pagejank1.png

圖11:時間軸上的動畫幀

即使渲染操作域屏幕刷新保持一致陋守,這些計算仍然運行在主線程上震贵,這也意味著當你的應用運行javascript時會阻塞。


pagejank2.png
pagejank2.png

圖12:時間軸上動畫幀水评,但一個幀被javascript阻止

你可以將Javascript操作分成小塊猩系,并使用requestAnimationFrame()安排在每個幀上運行。對于這個話題想要了解更多中燥,你可以看 js優(yōu)化執(zhí)行寇甸。你也可以讓你js運行在web woker上去避免阻塞主線程。

raf.png
raf.png

圖13:在帶有動畫幀的時間軸上運行javascript小塊

合成

你如何去畫一個頁面疗涉?

現(xiàn)在瀏覽器知道了文檔的結構拿霉,每個元素的樣式,在頁面里面的坐標和繪制順序咱扣,如何繪制一個頁面绽淘?將這些信息轉化為屏幕上的像素叫作光柵化(rasterizing)。

處理此問題的一個幼稚的方法就是在視口內部柵格化闹伪。如果用戶滾動頁面沪铭,則移動柵格化框架,并通過柵格化更多內容去填充缺失的部分偏瓤。這是Chrome第一次發(fā)布時處理柵格化的方式杀怠。然而,現(xiàn)代瀏覽器運行著更為復雜的過程厅克,叫作合成赔退。

什么是合成?

合成是將一個頁面的各個部分分成多個層,分別對其柵格化的技術硕旗,在一個叫作合成線程的獨立線程中合稱為一個頁面窗骑。如果發(fā)生滾動,由于圖層已經(jīng)被柵格化卵渴,所以就不得不合成一個新的幀慧域。可以使用相同的方式浪读,通過移動圖層生成一個新的幀來實現(xiàn)動畫昔榴。

你可以在開發(fā)者工具的“Layers panel”中查看你的網(wǎng)站如何被劃分為多個圖層。

劃分為圖層

為了找出哪些元素應該在哪些圖層碘橘,主線程遍歷布局樹為了生成圖層樹(在開發(fā)者工具中這部分在performance面板中被叫作“更新圖層樹”)互订。如果頁面的某些部分應該是獨立的層(例如滑入式側邊欄)沒有生成,你可以在css中使用 will-change 屬性去提示瀏覽器痘拆。

layer.png
layer.png

你可能試圖為每個元素提供圖層仰禽,但是與頁面的每幀進行柵格化相比,過多數(shù)量的圖層合成會使得操作速度變慢纺蛆,因此衡量應用程序的渲染性能特別重要吐葵。想了解更多這個話題,可以查看 Stick to Compositor-Only Properties and Manage Layer Count桥氏。

柵格化和合成脫離主線程

一旦圖層樹生成佳恬,并且繪制順序確定惨奕,主線程會提交這些信息給合成線程寇窑。合成器線程會柵格化每個圖層惋增。一個圖層可以和整個頁面的長度一樣大,因此合成器會講他們劃分為圖塊堕伪,并且將每個圖塊發(fā)送給柵格線程揖庄。柵格線程柵格化每個圖塊,并且將他們存儲在GPU中欠雌。

raster.png
raster.png

合成器線程會優(yōu)先處理不同的柵格線程蹄梢,因此可以首先對視口柵格化。一個圖層還具有不同分辨率的平鋪富俄,用于處理放大縮小的操作禁炒。

一旦圖塊被柵格化,合成器線程將手機信息叫作“draw quads”生成一個“compositor frame”蛙酪。

draw quads 包含例如圖塊在內存中位置以及考慮頁面合成的情況下在頁面中合成圖塊的信息。
compositor frame draw quads集合去展示一個頁面的框架

然后合成器框架通過IPC提交信息給瀏覽器進程翘盖。此時桂塞,可以從更改瀏覽器UI的UI線程或者另外一個用于擴展的渲染進程添加另一個合成器框架。這些合成框架都被發(fā)送到GPU用于顯示到屏幕上馍驯。如果滾動事件發(fā)生阁危,合成器進程創(chuàng)建另一個合成器框架發(fā)送給GPU玛痊。

composit.png
composit.png

合成的好處是不涉及主線程就可以完成。合成器線程不需要等到樣式計算和Js執(zhí)行狂打。這是為什么合成動畫被認為是最佳的平滑優(yōu)化的原因擂煞。如果布局和繪制需要重新計算,則必須涉及主線程趴乡。

總結

在這篇文章中对省,我們深入了解了從解析到合成的渲染流。希望你現(xiàn)在可以獲取到更多的關于網(wǎng)站優(yōu)化的知識晾捏。

在下面也是本系列最后一篇文章中蒿涎,我們將更加深入了解合成器線程,并且知道當用戶輸入例如mouse move和click的時候發(fā)生了什么惦辛。

?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末劳秋,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子胖齐,更是在濱河造成了極大的恐慌玻淑,老刑警劉巖,帶你破解...
    沈念sama閱讀 217,185評論 6 503
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件呀伙,死亡現(xiàn)場離奇詭異补履,居然都是意外死亡,警方通過查閱死者的電腦和手機区匠,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,652評論 3 393
  • 文/潘曉璐 我一進店門干像,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人驰弄,你說我怎么就攤上這事麻汰。” “怎么了戚篙?”我有些...
    開封第一講書人閱讀 163,524評論 0 353
  • 文/不壞的土叔 我叫張陵五鲫,是天一觀的道長。 經(jīng)常有香客問我岔擂,道長位喂,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,339評論 1 293
  • 正文 為了忘掉前任乱灵,我火速辦了婚禮塑崖,結果婚禮上,老公的妹妹穿的比我還像新娘痛倚。我一直安慰自己规婆,他們只是感情好,可當我...
    茶點故事閱讀 67,387評論 6 391
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著抒蚜,像睡著了一般掘鄙。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上嗡髓,一...
    開封第一講書人閱讀 51,287評論 1 301
  • 那天操漠,我揣著相機與錄音,去河邊找鬼饿这。 笑死浊伙,一個胖子當著我的面吹牛,可吹牛的內容都是我干的蛹稍。 我是一名探鬼主播吧黄,決...
    沈念sama閱讀 40,130評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼唆姐!你這毒婦竟也來了拗慨?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 38,985評論 0 275
  • 序言:老撾萬榮一對情侶失蹤奉芦,失蹤者是張志新(化名)和其女友劉穎赵抢,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體声功,經(jīng)...
    沈念sama閱讀 45,420評論 1 313
  • 正文 獨居荒郊野嶺守林人離奇死亡烦却,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 37,617評論 3 334
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了先巴。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片其爵。...
    茶點故事閱讀 39,779評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖伸蚯,靈堂內的尸體忽然破棺而出摩渺,到底是詐尸還是另有隱情,我是刑警寧澤剂邮,帶...
    沈念sama閱讀 35,477評論 5 345
  • 正文 年R本政府宣布摇幻,位于F島的核電站,受9級特大地震影響挥萌,放射性物質發(fā)生泄漏绰姻。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,088評論 3 328
  • 文/蒙蒙 一引瀑、第九天 我趴在偏房一處隱蔽的房頂上張望狂芋。 院中可真熱鬧,春花似錦憨栽、人聲如沸帜矾。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,716評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽黍特。三九已至,卻和暖如春锯蛀,著一層夾襖步出監(jiān)牢的瞬間灭衷,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,857評論 1 269
  • 我被黑心中介騙來泰國打工旁涤, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留翔曲,地道東北人。 一個月前我還...
    沈念sama閱讀 47,876評論 2 370
  • 正文 我出身青樓劈愚,卻偏偏與公主長得像瞳遍,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子菌羽,可洞房花燭夜當晚...
    茶點故事閱讀 44,700評論 2 354

推薦閱讀更多精彩內容

  • 瀏覽器的渲染過程 在我們面試過程中掠械,經(jīng)常會遇到面試官問我們,當我們從瀏覽器地址欄輸入URL之后到頁面顯示注祖,瀏覽器到...
    達文西_Huong閱讀 865評論 0 0
  • 1.瀏覽器的發(fā)展史 1992年猾蒂,托尼喲翰遜(Tony Johnson)發(fā)布了Midas,它允許用戶瀏覽UNIX和V...
    不會飛的fish閱讀 535評論 0 0
  • 瀏覽器組成 用戶界面 :展示除標簽頁窗口之外的其他用戶界面內容 瀏覽器引擎:在用戶界面和渲染引擎之間傳遞數(shù)據(jù)是晨,具有...
    杉綠閱讀 171評論 0 1
  • 瀏覽器架構 在講瀏覽器架構之前肚菠,先理解兩個概念,進程和線程罩缴。 進程(process)是程序的一次執(zhí)行過程蚊逢,是一個動...
    淺時咣閱讀 360評論 0 2
  • 一、瀏覽器如何渲染網(wǎng)頁 要了解瀏覽器渲染頁面的過程箫章,首先得知道一個名詞——關鍵路徑渲染烙荷。關鍵渲染路徑(Critic...
    Srtian閱讀 998評論 1 3