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