瀏覽器內核包括渲染引擎和JS引擎,因爲js引擎愈來愈獨立,內核就傾向於只指渲染引擎html
渲染引擎是一種對HTML文檔進行解析並將其顯示在頁面上的工具。它負責取得網頁的內容(HTML、XML、圖象等等)、整理信息(例如加入CSS等),以及計算網頁的顯示方式而後會輸出至顯示器或打印機web
渲染引擎工做流程正則表達式
HTML解析器解析DOMM樹(解析爲DOM樹上個節點,同時解析CSS樣式)算法
渲染樹結構(具備必定的視覺效果,並按照必定順序排列在屏幕上)後端
佈局渲染樹(爲每一個節點分配固定座標)瀏覽器
繪製DOM樹(渲染引擎會遍歷全部的節點,由UI後端繪製)緩存
Webkit工做流程網絡
Gecko工做流程框架
Webkit和gecko屬於不一樣,但流程基本相同。 Gecko將視覺化後的樹稱爲「框架樹」,webkit稱爲「渲染樹」;對於元素的排放,webkit稱爲「佈局layout」,gecko稱爲「重拍reflow」;gecko在html解析和DOM樹間添加了「內容槽」,用於生成DOM元素;將DOM樹和樣式信息構建渲染樹的過程,webkit稱爲「附加」,gecko稱爲「框架結構」。異步
1解析
將文檔轉化爲代碼可使用的結構,解析的結果表明了文檔結構的節點樹,也稱爲解析樹。
解析器分兩個結構:詞法分析和語法分析 詞法分析負責將輸入內容分解爲有效標記符號;語法分析對語言應用語法規則,從而構建解析樹。
解析是一個迭代的過程。一般,解析器會向詞法分析器請求一個新標記,並嘗試將其與某條語法規則進行匹配。若是發現了匹配規則,解析器會將一個對應於該標記的節點添加到解析樹中,而後繼續請求下一個標記。 若是沒有規則能夠匹配,解析器就會將標記存儲到內部,並繼續請求標記,直至找到可與全部內部存儲的標記匹配的規則。若是找不到任何匹配規則,解析器就會引起一個異常。這意味着文檔無效,包含語法錯誤。
轉換:將解析樹轉換成機器代碼語言。 自動生成解析器: WebKit 使用了兩種解析器生成器:用於建立詞法分析器的 Flex 和用於建立解析器的 Bison。Flex 的輸入是包含標記的正則表達式定義的文件。Bison 的輸入是採用 BNF 格式的語言語法規則。 HTML DTD Html適用DTD格式進行定義,這一格式是用於定義SGML家族的語言,包括了對全部容許元素及它們的屬性和層次關係的定義。
DOM 輸出的樹,也就是解析樹,是由DOM元素及屬性節點組成的。DOM是文檔對象模型的縮寫,它是html文檔的對象表示,做爲html元素的外部接口供js等調用。
1-1 HTML解析器 將HTML解析器解析成解析樹 解析算法: 此算法由兩個階段組成:標記化和樹構建。
標記化是詞法分析過程,將輸入內容解析成多個標記。HTML 標記包括起始標記、結束標記、屬性名稱和屬性值。
標記化算法 該算法的輸出結果是 HTML 標記。該算法使用狀態機來表示。每個狀態接收來自輸入信息流的一個或多個字符,並根據這些字符更新下一個狀態。當前的標記化狀態和樹結構狀態會影響進入下一狀態的決定。這意味着,即便接收的字符相同,對於下一個正確的狀態也會產生不一樣的結果,具體取決於當前的狀態。
樹構建算法 在樹構建階段,以 Document 爲根節點的 DOM 樹也會不斷進行修改,向其中添加各類元素。標記生成器發送的每一個節點都會由樹構建器進行處理。 規範中定義了每一個標記所對應的 DOM 元素,這些元素會在接收到相應的標記時建立。這些元素不只會添加到 DOM 樹中,還會添加到開放元素的堆棧中。此堆棧用於糾正嵌套錯誤和處理未關閉的標記。其算法也能夠用狀態機來描述。這些狀態稱爲「插入模式」 解析結束後的操做 在此階段,瀏覽器會將文檔標註爲交互狀態,並開始解析在文檔解析完成後才執行的腳本。而後,文檔狀態將設置爲「完成」,一個「加載」事件將隨之觸發。
Webkit容錯機制
(1)明顯不能在某些外部標記中添加的元素。在此狀況下,咱們應該關閉全部標記,直到出現禁止添加的元素,而後再加入該元素。
(2)咱們不能直接添加的元素。這極可能是網頁做者忘記添加了其中的一些標記(或者其中的標記是可選的)。這些標籤可能包括:HTML HEAD BODY TBODY TR TD LI(還有遺漏的嗎?)
(3)向 inline 元素內添加 block 元素。關閉全部 inline 元素,直到出現下一個較高級的 block 元素。
(4)若是這樣仍然無效,可關閉全部元素,直到能夠添加元素爲止,或者忽略該標記。
1-2CSS解析器
CSS 是上下文無關的語法。 詞法語法(詞彙)是針對各個標記用正則表達式定義 WebKit CSS 解析器 WebKit 使用 Flex 和 Bison 解析器生成器,經過 CSS 語法文件自動建立解析器。 Bison 會建立自下而上的移位歸約解析器。Firefox 使用的是人工編寫的自上而下的解析器。 都會將 CSS 文件解析成 StyleSheet 對象,且每一個對象都包含 CSS 規則。CSS 規則對象則包含選擇器和聲明對象,以及其餘與 CSS 語法對應的對象。
1-3 處理腳本和樣式表的順序
腳本
網絡的模型是同步的。 解析器遇到解析器遇到<script> 標記時當即解析並執行腳本。文檔的解析將中止,直到腳本執行完畢。若是腳本是外部的,那麼解析過程會中止,直到從網絡同步抓取資源完成後再繼續。在 HTML4 和 HTML5 規範中將腳本標註爲「defer」,這樣不會中止文檔解析,而是等到解析結束才執行。HTML5 增長了一個選項,可將腳本標記爲異步,以便由其餘線程解析和執行。
預解析
在執行腳本時,其餘線程會解析文檔的其他部分,找出並加載須要經過網絡加載的其餘資源。經過這種方式,資源能夠在並行鏈接上加載,從而提升整體速度。,預解析器不會修改 DOM 樹,而是將這項工做交由主解析器處理;預解析器只會解析外部資源(例如外部腳本、樣式表和圖片)的引用。
樣式表
應用樣式表不會更改 DOM 樹,所以彷佛沒有必要等待樣式表並中止文檔解析。但腳本在文檔解析階段會請求樣式信息。若是當時尚未加載和解析樣式,腳本就會得到錯誤的回覆。解決方案:Firefox, 在樣式表加載和解析的過程當中,會禁止全部腳本。WebKit,僅當腳本嘗試訪問的樣式屬性可能受還沒有加載的樣式表影響時,纔會禁止該腳本。
2渲染樹構建
做用:按照正確的順序繪製內容。根據 display 屬性的不一樣,針對同一個 DOM 節點應建立什麼類型的呈現器。
與DOM樹區別:非可視化的 DOM 元素不會插入渲染樹中,例如「head」元素。若是元素的 display 屬性值爲「none」,那麼也不會顯示在渲染樹中(可是 visibility 屬性值爲「hidden」的元素仍會顯示)。有一些 DOM 元素對應多個可視化對象。它們每每是具備複雜結構的元素,沒法用單一的矩形來描述,如select;關於多呈現器的例子是格式無效的 HTML;渲染對象對應於 DOM 節點,但在樹中所在的位置與 DOM 節點不一樣。浮動定位和絕對定位的元素
構建渲染樹流程: Firework,系統針對DOM更新註冊展現層,做爲偵聽器。展現層將框架建立工做委託給FrameConstructor,由該構造器解析樣式並建立框架。 Webkit,解析樣式和建立render器的過程稱爲「附加」,每個DOM節點都會有附加方法。 處理html和body標記就會建立渲染樹的根節點。由根節點渲染對象就是CSS中所說的容器block,它是最頂層的block,其他的block都被它包含。它的大小就是瀏覽器視圖的大小。渲染樹的其他部分都是做爲DOM樹節點形式被插入到渲染樹中的。
2-1計算樣式
計算渲染對象的可視化屬性,就是計算每一個元素的樣式屬性。 難點:樣式數據大;元素匹配複雜;應用規則涉及到複雜的層疊規則
2-2 計算順序
3 佈局
渲染樹並不包含位置和大小信息,計算這些信息的過程稱爲佈局或重排。
HTML採用基於流的佈局模型,只須要遍歷一次就能夠計算出全部的幾何信息。處於流後面位置的元素不會影響前面元素的幾何特徵。佈局能夠按照從左至右,從上至下的順序遍歷文檔。 佈局是個遞歸的過程,它從根渲染器開始而後遞歸遍歷全部子渲染器,具備子渲染器的渲染器繼續遞歸遍歷遍歷全部子渲染器。每一個渲染器都有一個「layout」或「reflow」方法,每一個渲染器都會調用須要進行佈局的子代的layout方法。
Dirty位系統
做用:避免細小的變化影響總體佈局。 若是渲染器發生了變化或者其子代發生了變化就會被標註爲」dirty」或children are dirty,須要進行佈局。
全局佈局和增量佈局
全局佈局:是指觸發了整個渲染樹的佈局,觸發緣由:1 影響全部渲染器的全局樣式發生了改變,好比size變化。2 屏幕尺寸發生變化。
增量佈局:只對標記爲dirty的渲染器佈局。 異步佈局和同步佈局 增量佈局是異步執行的。Firefox將增量佈局的「reflow 命令」加入隊列,調度程序會觸發批量觸發這些命令。
Webkit 有一個定時器來執行增量佈局,對渲染樹遍歷,並對有dirty標記的渲染器進行佈局。 全局佈局是同步觸發的。初始佈局完成以後,若是一些屬性(如滾動位置)發生變化,佈局就會做爲回調觸發。
佈局處理
(1) 父呈現器肯定本身的寬度。
(2) 父呈現器依次處理子呈現器,而且: 放置子呈現器(設置 x,y 座標)。 若是有必要,調用子呈現器的佈局(若是子呈現器是 dirty 的,或者這是全局佈局,或出於其餘某些緣由),這會計算子呈現器的高度。
(3) 父呈現器根據子呈現器的累加高度以及邊距和補白的高度來設置自身高度,此值也可供父呈現器的父呈現器使用。
(4) 將其 dirty 位設置爲 false 寬度計算 呈現器寬度是根據容器塊的寬度、呈現器樣式中的「width」屬性以及邊距和邊框計算得出的
4繪製
遍歷渲染樹,並調用渲染器的「paint」方法,將渲染器的內容顯示在屏幕上。繪製工具是使用用戶界面基本組件完成的。
全局繪製和增量繪製
繪製也分爲全局繪製和增量繪製。
在增量繪製中,部分渲染器發生變化不影響整個樹。 更改後的呈現器將其在屏幕上對應的矩形區域設爲無效,這致使 OS 將其視爲一塊「dirty 區域」,並生成「paint」事件。OS 會很巧妙地將多個區域合併成一個。在 Chrome 瀏覽器中,狀況要更復雜一些,由於 Chrome 瀏覽器的呈現器不在主進程上。Chrome 瀏覽器會在某種程度上模擬 OS 的行爲。展現層會偵聽這些事件,並將消息委託給呈現根節點。而後遍歷呈現樹,直到找到相關的呈現器,該呈現器會從新繪製本身(一般也包括其子代)
繪製順序
繪製的順序其實就是元素進入堆棧樣式上下文的順序。這些堆棧會從後往前繪製,所以這樣的順序會影響繪製。塊呈現器的堆棧順序以下:
背景顏色,背景圖片,邊框,子代,輪廓
5動態變化
在發生變化時,瀏覽器會盡量作出最小的響應。所以,元素的顏色改變後,只會對該元素進行重繪。元素的位置改變後,只會對該元素及其子元素(可能還有同級元素)進行佈局和重繪。添加 DOM 節點後,會對該節點進行佈局和重繪。一些重大變化(例如增大「html」元素的字體)會致使緩存無效,使得整個呈現樹都會進行從新佈局和繪製。
6渲染引擎的線程
除了網絡操做之外,幾乎全部操做都採用單線程。
在 Firefox 和 Safari 中,該線程就是瀏覽器的主線程。而在 Chrome 瀏覽器中,該線程是標籤進程的主線程。 網絡操做可由多個並行線程執行。並行鏈接數是有限的(一般爲 2 至 6 個,以 Firefox 3 爲例是 6 個)。 事件循環 瀏覽器的主線程是事件循環,它是無線循環的,永遠處於接收狀態,並等待(如佈局和繪製事件)發生,並進行處理
7 CSS2可視化模型
畫布
CSS框模型
定位方案
(1) 普通,根據對象在文檔中的位置進行定位。
(2) 浮動,先按照普通流定位,再儘量的左右上下移動
(3) 局對,對象在渲染樹中的位置和它在DOM樹中的位置不一樣 定位方案是由「position」屬性和「float」屬性設置的。
若是值是 static 和 relative,就是普通流 若是值是 absolute 和 fixed,就是絕對定位 框類型 block 框:造成一個 block,在瀏覽器窗口中擁有其本身的矩形區域 inline 框:沒有本身的 block,可是位於容器 block 內 block 採用的是一個接一個的垂直格式,而 inline 採用的是水平格式
定位
分層展現
這是由 z-index CSS 屬性指定的。它表明了框的第三個維度,也就是沿「z 軸」方向的位置。 這些框分散到多個堆棧(稱爲堆棧上下文)中。在每個堆棧中,會首先繪製後面的元素,而後在頂部繪製前面的元素,以便更靠近用戶。若是出現重疊,新繪製的元素就會覆蓋以前的元素。 堆棧是按照 z-index 屬性進行排序的。具備「z-index」屬性的框造成了本地堆棧。視口具備外部堆棧。