前言
對于HTML,css和JavaScript是如何變成頁面的,這個問題你了解過嗎?瀏覽器究竟在背后都做了些什么事情呢?讓我們?nèi)チ私鉃g覽器的渲染原理,是通往更深層次的開發(fā)必不可少的事情,能讓我們更深層次,多角度的去考慮性能優(yōu)化等問題。
HTML,css,JavaScript數(shù)據(jù)經(jīng)過中間渲染模塊的處理,最終顯示在頁面上(其中HTML超文本標記語言,CSS層疊樣式表,JS為JavaScript,大家一般都知道是什么,寫過網(wǎng)頁的朋友,學習者大都知道的)。
-
HTML的內(nèi)容是由標記和文本組成 -
CSS稱為層疊樣式表,是由選擇器和屬性組成 -
JS是可以使網(wǎng)頁的內(nèi)容“動”起來
有人說渲染流程可以分為:構建DOM樹,樣式計算,布局階段,分層,繪制,分塊,光柵化和合成等。其中瀏覽器復習一下,它是多線程的的,js是單線程的,JS在瀏覽器中,它可以是多線程的。
下面圍繞瀏覽器渲染原理話題開始描述,為什么要了解瀏覽器渲染頁面機制呢?接下來讓我慢慢告訴你:
瀏覽器渲染原理
首先,JavaScript引擎是基于事件驅(qū)動單線程執(zhí)行的,渲染線程負責渲染瀏覽器界面,但是GUI渲染線程與JS引擎是互斥的,當JS引擎執(zhí)行時GUI線程會被掛起,GUI的更新也會被保存在一個隊列中,等到JS引擎空閑時才有機會被執(zhí)行。
那么什么是DOCTYPE以及作用呢
DTD,document type definition, 文檔類型定義,是一系列的語法規(guī)則,用來定義XML或(x)HTML的文件類型。瀏覽器會使用它來判斷文檔類型,決定使用何種協(xié)議來解析,以及切換瀏覽器模式。
DOCTYPE是用來聲明文檔類型和DTD規(guī)范的,一個主要的用途便是文件的合法性驗證。如果文件代碼不合法,那么瀏覽器解析時便會出一些差錯。
下圖為瀏覽器的渲染過程圖:
重排Reflow
重排的定義:DOM結構中的各個元素都有自己的盒子模型,這些都需要瀏覽器根據(jù)各種樣式來計算并根據(jù)計算結果將元素放到它該出現(xiàn)的位置,這個過程稱之為reflow.
觸發(fā)Reflow情況
-
當你增加,刪除,修改Dom節(jié)點時會導致Reflow或Repaint -
當你移動DOM的位置,或是搞個動畫的時候 -
當你修改CSS樣式的時候 -
當你Resize窗口的時候,或是滾動的時候 -
當你修改網(wǎng)頁的默認字體時
重繪Repaint
重繪的定義,當各種盒子的位置,大小以及其他屬性,例如顏色,字體大小等都確定下來后,瀏覽器于是便把這些元素都按照各自的特性繪制了一遍,于是頁面的內(nèi)容出現(xiàn)了,這個過程稱為repaint。
觸發(fā)Repaint情況
-
DOM改動 -
CSS改動
講到這里,下面來細分說一下吧!
簡單介紹一下瀏覽器的工作原理
-
了解瀏覽器
目前使用的主流的瀏覽器:Internet Explorer,F(xiàn)irefox,Safari,Chrome瀏覽器,Opera。讓我們看看瀏覽器統(tǒng)計數(shù)據(jù)的占比:
讓你說說瀏覽器的主要功能:
就是向服務器發(fā)出請求,在瀏覽器窗口中展示您選擇的網(wǎng)絡資源,資源一般指HTML文檔,可以是PDF,圖片或其他的類型。資源的位置由用戶使用URI(在電腦術語中,統(tǒng)一資源標識符(Uniform Resource Identifier,URI)是一個用于標識某一互聯(lián)網(wǎng)資源名稱的字符串)
-
瀏覽器的結構
-
用戶界面:包括地址欄,前進、后退按鈕,書簽菜單等。 -
瀏覽器引擎:在用戶界面和呈現(xiàn)引擎之間傳送指令。 -
呈現(xiàn)引擎:負責顯示請求的內(nèi)容。 -
網(wǎng)絡:用于網(wǎng)絡調(diào)用,比如HTTP請求;其接口與平臺無關,并為所有平臺提供底層實現(xiàn)。 -
用戶界面后端:用于繪制基本的窗口小部件,比如組合框和窗口。其公開了與平臺無關的通用接口,而在底層使用操作系統(tǒng)的用戶界面方法。 -
JavaScript解釋器:用于解析和執(zhí)行JavaScript代碼。 -
數(shù)據(jù)存儲:這是持久層。瀏覽器需要在硬盤上保存各種數(shù)據(jù),例如Cookie。新的HTML規(guī)范定義了“網(wǎng)絡數(shù)據(jù)庫”,這是一個完整的瀏覽器內(nèi)數(shù)據(jù)庫。
注意:Chrome瀏覽器的每個標簽頁都分別對應一個呈現(xiàn)引擎實例,每個標簽頁都是一個獨立的進程。
-
呈現(xiàn)引擎
呈現(xiàn)引擎的作用是“呈現(xiàn)”,用于在瀏覽器的屏幕上顯示請求的內(nèi)容。
一般情況下,呈現(xiàn)引擎可顯示HTML和xml文檔與圖片,通過插件或瀏覽器擴展程序,可以顯示其他類型的內(nèi)容。瀏覽器(Firefox,Chrome瀏覽器和Safari)是基于兩種呈現(xiàn)引擎構建的。
Firefox使用的是Gecko,而Safari和Chrome瀏覽器使用的是WebKit(WebKit 是一種開放源代碼呈現(xiàn)引擎)。
-
主流程
呈現(xiàn)引擎一開始會從網(wǎng)絡層獲取請求文檔的內(nèi)容,其大小一般限制在8000個塊以內(nèi)。
呈現(xiàn)引擎將開始解析HTML文檔,并將各標記逐個轉(zhuǎn)化成“內(nèi)容樹”上的DOM節(jié)點。同時也會解析外部CSS文件以及樣式元素中的樣式數(shù)據(jù)。呈現(xiàn)樹構建完后,會進入“布局”處理階段,也就是為每個節(jié)點分配一個應出現(xiàn)在屏幕上的確切坐標。
-
解析
解析是呈現(xiàn)引擎中重要的環(huán)境,什么是解析呢?
解析文檔是指將文檔轉(zhuǎn)化成為有意義的結構,可以讓代碼理解和使用的結構。解析得到的結構通常是代表了文檔結構的節(jié)點樹,它稱為解析樹或者語法樹。
-
語法
解析是以文檔所遵循的語法規(guī)則為基礎的。解析的過程分為兩個子過程:詞法分析和語法分析。
什么是詞法分析呢?
詞法分析是將輸入內(nèi)容分割成大量標記的過程,標記(語言中的詞匯),構成內(nèi)容的單位。相等于語言中的單詞。
什么是語法分析呢?
語法分析是應用語言的語法規(guī)則的過程。
so,解析器一般解析工作分兩個組件處理,為詞法分析器(負責將輸入內(nèi)容分解成一個個有效標記),解析器負責根據(jù)語言的語法規(guī)則來分析文檔的結構,來構建解析樹。
從源文檔到解析樹:Document->Lexical Analysis->Syntax Analysis->Parse Tree
解析是一個迭代的過程。
是這樣的,解析器會向詞法分析器請求一個新標記,并嘗試將其與某條語法規(guī)則進行匹配。如果匹配規(guī)則,解析器就會將對應與該標記的節(jié)點添加到解析樹中,然后繼續(xù)下一個。
但是如果沒有匹配的規(guī)則,解析器會將標記存儲到內(nèi)部,繼續(xù)請求標記,直到可與之匹配的規(guī)則,但是如果沒有直到的話,就會引發(fā)異常(文檔無效,包含語法錯誤等)。
-
翻譯
解析通常是在翻譯的過程中,而翻譯是將輸入的文檔轉(zhuǎn)換為另一種形式,如編譯器將源代碼編譯成機器代碼,流程是將源代碼解析成解析樹,將解析樹翻譯成機器代碼文檔。
編譯流程:Source Code -> Parsing->Parse Tree -> Translation -> Machine Code
-
解析器類型
兩種基本的解析器類型:自上而下解析器,自下而上解析器
自上而下就是: 解析器從語法的高層結構出發(fā),嘗試從中找到匹配的結構。
自下而上就是: ?解析器從低層規(guī)則出發(fā),將輸入內(nèi)容逐步轉(zhuǎn)化為語法規(guī)則,直至滿足高層規(guī)則。
你知道一種工具叫解析器生成器嗎,它能夠幫助你生成解析器,你只要向它提供你所使用的語言的語法,即詞匯和語法規(guī)則,然后就會生成相應的解析器。
你暈了嗎?可以點擊這里查看:瀏覽器的工作原理:新式網(wǎng)絡瀏覽器幕后揭秘 https://www.html5rocks.com/zh/tutorials/internals/howbrowserswork/
渲染機制
瀏覽器從接收到頁面開始到頁面顯示,這整個過程中的所有步驟,稱 關鍵渲染路徑 ,一般分為兩步:頁面內(nèi)容加載完成和頁面資源完成,分別對應于DOMContentLoaded和Load
關鍵:網(wǎng)頁的渲染過程如下,包含頁面加載和頁面渲染兩個過程。
頁面加載過程是,從服務器請求資源并構建DOM樹的過程,網(wǎng)頁渲染過程指的是通過DOM樹渲染出視圖內(nèi)容。
首先 瀏覽器加載網(wǎng)頁內(nèi)容,使用HTML解釋器?將網(wǎng)頁?轉(zhuǎn)變 為一系列的 token,再根據(jù)token 構建 dom 樹, 當一個可見的 dom 節(jié)點 插入到dom 樹時,瀏覽器會構建一個renderObject 節(jié)點并將其插入到 render 樹中。
Render 樹包含節(jié)點的樣式信息,可以簡單理解為 dom + css構成。Render樹將交由排版引擎處理,計算出每一個RenderObject 節(jié)點的大小和位置等信息,然后再交給由渲染引擎完成頁面的內(nèi)容繪制。
DOM + CSS -> Render Tree
復習一下整個關鍵渲染包括:
-
解析HTML,生成DOM樹(DOM) -
解析CSS,生成CSSOM樹 -
將DOM和CSSOM合并,生成渲染樹(Rendere-Tree) -
計算渲染樹的布局Layout -
將布局渲染到屏幕上Paint
那么要問了,為什么要了解瀏覽器渲染頁面機制呢?
了解渲染機制,主要還是為了性能的優(yōu)化:
了解瀏覽器如何進行加載,引用外部樣式文件,JS文件時,將它們放到合適的位置,是瀏覽器最快的速度讓文件加載完畢;了解瀏覽器如何進行解析,選擇最優(yōu)的寫法,構建DOM結構,組織CSS選擇器的時候,是為了提高瀏覽器的解析速率;了解瀏覽器如何進行渲染,是可以減少“重繪”,“重新布局”的消耗。
那么上面一直說了解渲染機制,出現(xiàn)的幾個基本概念,這里先弄明白:
-
DOM: Document Object Model,瀏覽器將HTML解析成樹形的數(shù)據(jù)結構 -
CSSOM: CSS Object Model,瀏覽器將CSS解析成樹形的數(shù)據(jù)結構 -
Render Tree: DOM和CSSOM合并生成Render Tree -
Layout: 計算出Render Tree每個節(jié)點的具體位置 -
Painting: 通過顯卡,將Layout后的節(jié)點內(nèi)容分別呈現(xiàn)到屏幕上
當瀏覽器獲取HTML文件后,會自上而下加載并在加載過程中進行解析和渲染;加載就是獲取資源的過程;如果在加載過程中遇到外部的css文件和圖片,瀏覽器會另外發(fā)送一個請求,去獲取css文件和圖片,這個請求是異步的,并不會影響HTML文件的加載;但如果遇到JavaScript文件,HTML文件會掛起渲染的進程,等待JavaScript文件加載完畢后,再繼續(xù)進行渲染。
為什么需要等待JavaScript呢?
因為JavaScript可能會修改dom,導致后面的HTML資源白白加載,需要等待JavaScript文件加載完成后,再繼續(xù)渲染,so,JavaScript文件一般寫在底部body標簽前的原因。
說說瀏覽器頁面渲染:
-
第一步:在CSS資源還沒有請求回來之前,先生成DOM樹; -
第二步:當所有的CSS請求回來之后,瀏覽器按照CSS的導入順序,依次進行渲染,最后生成CSSOM樹; -
第三步:把DOM樹和CSSOM樹結合在一起,生成有樣式,有結構的RENDER TREE渲染樹; -
最后一步:瀏覽器按照渲染樹,在頁面中進行渲染和解析
由于渲染機制過于復雜,渲染模塊在在執(zhí)行過程中劃分了很多階段,通過《瀏覽器工作原理與實踐》-渲染流程上分:構建DOM樹,樣式計算,布局階段;渲染流程下分:分層,圖層繪制,柵格化(raster)操作,合成和顯示。
整個渲染流程,從HTML到DOM、樣式計算、布局、圖層、繪制、光柵化、合成和顯示。
面試一問:為什么要構建DOM樹?
答:因為瀏覽器不能直接理解和使用HTML,so,需要將HTML轉(zhuǎn)換為瀏覽器能夠理解的結構,即是DOM樹(樹結構一般都了解了的)。
為了了解完整的DOM樹結構,可以打開Chrome的“開發(fā)者工具”,或按F12,如圖下:
接下來要讓DOM節(jié)點擁有正確的樣式,這就需要樣式計算了。
樣式計算的目的是為了計算出DOM節(jié)點中每個元素的具體樣式:三步走
-
把CSS轉(zhuǎn)換為瀏覽器能夠理解的結構 -
轉(zhuǎn)換樣式表中的屬性值,使其標準化 -
計算出DOM樹中每個節(jié)點的具體樣式(涉及到CSS的繼承規(guī)則和層疊規(guī)則)
當渲染引擎接收到CSS文本時,會執(zhí)行一個轉(zhuǎn)換操作,將CSS文本轉(zhuǎn)換為瀏覽器可以理解的結構——styleSheets。屬性值標準化的過程:將所有值轉(zhuǎn)換為渲染引擎容易理解的、標準化的計算值。
DOM元素最終計算的樣式如圖:
布局階段
布局:計算出DOM樹中可見元素的幾何位置,第一創(chuàng)建布局樹(構建一棵只包含可見元素布局樹),第二布局計算。
面試問題:CSS加載會阻塞頁面顯示嗎?
-
css加載不會阻塞DOM樹的解析 -
css加載會阻塞DOM樹的渲染 -
css加載會阻塞后面js語句的執(zhí)行
so,為了避免讓用戶看到長時間的白屏時間,應該提高css的加載速度。
為了防止css阻塞,引起頁面白屏,可以提高頁面加載速度
-
使用cdn -
對css進行壓縮 -
合理利用緩存 -
減少http請求,將多個css文件合并
面試問題:下載CSS文件阻塞了,會阻塞DOM樹的合成嗎?會阻塞頁面的顯示嗎?
答:不會阻塞dom樹構建的,因為HTML轉(zhuǎn)化為dom樹的過程,發(fā)現(xiàn)文件請求會交給網(wǎng)絡進程去請求對應文件,渲染進程繼續(xù)解析HTML。
會阻塞頁面的顯示,當計算樣式的時候需要等待css文件的資源進行層疊樣式,資源阻塞了,會進行等待,直到網(wǎng)絡超時,network報出錯誤,渲染進程繼續(xù)層疊樣式計算。
說了DOM生成、樣式計算和布局三個階段,接下來說說后面的階段。
說說分層:渲染引擎給頁面分了很多圖層,這些圖層按照一定順序疊加在一起,就形成了最終的頁面。完成圖層樹的構建后,渲染引擎會對圖層樹中的每個圖層進行繪制,為圖層繪制。然后進行柵格化(raster)操作(繪制列表只是用來記錄繪制順序和繪制指令的列表,而實際上繪制操作是由渲染引擎中的合成線程來完成的),最后合成與顯示。
頁面渲染機制圖如下:
渲染過程圖如下:
瀏覽器渲染過程如下:
這里重點要說(重新說一下)兩個概念回流和重繪:
當render tree中的一部分因為元素的規(guī)模尺寸,布局,隱藏等改變而需要重新構建。這就稱為回流(reflow)。
每個頁面至少需要一次回流,就是在頁面第一次加載的時候。
在回流的時候,瀏覽器會使渲染樹中受到影響的部分失效,并重新構造這部分渲染樹,完成回流后,瀏覽器會重新繪制受影響的部分到屏幕中,該過程成為重繪。
當render tree中的一些元素需要更新屬性,而這些屬性只是影響元素的外觀,風格,而不會影響布局的,比如background-color。就叫稱為重繪。
本篇文章的最后,留下一道思考題:減少重繪/重排能優(yōu)化Web性能嗎?如何能減少重繪/重排?
參考資料
-
https://www.cnblogs.com/jianjie/p/13229789.html -
https://zhuanlan.zhihu.com/p/26105913 -
瀏覽器工作原理與實踐 -
https://segmentfault.com/a/1190000018811208
總結
以上就是今天要講的內(nèi)容,本文簡單介紹了Chrome瀏覽器的渲染原理流程。如果你覺得這篇文章對你有幫助的話,也歡迎把它分享給更多的朋友。
—————END—————
喜歡本文的朋友,歡迎關注公眾號?程序員小灰,收看更多精彩內(nèi)容
點個[在看],是對小灰最大的支持!
免責聲明:本文內(nèi)容由21ic獲得授權后發(fā)布,版權歸原作者所有,本平臺僅提供信息存儲服務。文章僅代表作者個人觀點,不代表本平臺立場,如有問題,請聯(lián)系我們,謝謝!