瀏覽器顯示及交互背後的原理

瀏覽器顯示及交互背後的原理

引子

因爲筆者(愛編程的光頭強)近期在寫一本關於小程序入門的書籍。其中有一章是介紹虛擬DOM的,它是位於Javascript和真正DOM之間的一層緩存層。爲什麼引入它,爲什麼它這麼流行,前端三大框架,小程序等,隨處可見它的身影。其背後原理是什麼。不基於瀏覽器背後的運行原理,是很難說清楚虛擬DOM被引入的真正原因和最大好處的。

爲了弄清楚瀏覽器背後運行的邏輯,我查了大量資料,不得不吐槽一下,互聯網知識儘管多,魚龍混雜、參差不齊、錯漏百出,基本是常態,能找到一篇含金量十分高的文章是不容易的。很幸運,關於這個問題,我還真找到了一篇,本文就是對它的解讀。好記性不如爛筆頭。

注:本文所有網址都是經過百度短網址處理過的,便於排版及美觀。

原文引用

正文

本文相當於一篇讀書筆記,我們按照原文順序來一點點深入。 瀏覽器市場份額佔比: Chrome 63.34% Safari 15.06% Firefox 4.48% Samsung Internet 3.77% UC Browser 3.58% Opera 2.58% 從以上瀏覽器份額,可以看出,chrome佔絕對比,所以我們的測試就基於它。

一、瀏覽器引擎

引擎的通俗解釋就是驅動器、發動機,在軟件中是以一套組件或者擴展程序、包存在的核心代碼,相當於計算機的CPU。Wikipedia的解釋是瀏覽器引擎即佈局引擎,排版引擎,渲染引擎等。Chrome、Safari使用的是Webkit引擎,Mozilla使用的是Gecho引擎,有時候也叫內核。參考:Https://Dwz.Cn/Tr3rrt8m

以上定義對大衆是足夠的,但對於想搞清楚瀏覽器運行機制的人來說,不夠。很顯然,它籠統的將瀏覽器幾塊核心程序(引擎)統稱爲一個了,並使用其中一個作爲全部核心的代稱,這很容易讓人混淆。

果然,stackoverflow就有人提到了這樣的混淆(https://dwz.cn/7ccPJcX6), 本文引用的以色列那位女工程師文章中,將瀏覽器組件分爲了7個,用戶界面(UI),瀏覽器引擎,呈現引擎,網絡,用戶界面後端,JavaScript 解釋器,數據存儲等。

ui,瀏覽器引擎,渲染引擎等之間關係圖

ui,瀏覽器引擎,渲染引擎等之間關係圖

各瀏覽器使用的渲染/layout引擎及js引擎表

各瀏覽器使用的渲染/layout引擎及js引擎表

這裏的瀏覽器引擎到底指什麼呢,很顯然它並不是wikipedia裏的大衆解釋,stackoverflow有個答案我覺得比較靠譜,它的解釋基於chrome瀏覽器的多進程架構,筆者(愛編程的光頭強)使用chrome自帶的中文翻譯,翻譯了這段,供大家參考:

回答一:

我不知道如何用“引擎”來解釋。讓我通過在具有多進程架構的chrome瀏覽器的上下文中使用的“【

瀏覽器主進程:管理渲染器進程的主瀏覽器進程。 渲染器進程:基本上可理解爲一個標籤卡(chrome)。

可能因爲惡意Web內容,導致整個瀏覽器崩潰或危及宿主機系統,爲了防止這種情況發生,瀏覽器進程委託單獨的渲染進程(Renderer進程(選項卡進程))處理每個請求的Web內容,它沒有用戶權限(即對OS系統調用的訪問權限有限)。

當請求網站時,渲染進程將請求轉發到瀏覽器進程,進而發起對導航網站的網絡請求。在Web內容到達之後,瀏覽器進程將內容發送回渲染進程。渲染器進程解析HTML,CSS文件,準備DOM,CSSOM,維護JS運行時(V8實例)並將內容作爲位圖格式發送到瀏覽器進程以在UI上顯示它。

瀏覽器進程將渲染器進程視爲黑盒子,期望渲染器進程將某種格式的Web內容轉換爲所需格式,其中包括幾個子組件,佈局引擎(進程,layout(chrome)/reflow(mozilla)是其中一個。

因此,瀏覽器進程處理用戶特權資源/請求,例如訪問文件系統,網絡等,其中沙盒渲染器進程負責將網頁轉換爲瀏覽器進程可以將其顯示在OS窗口管理器中的格式。

這其中涉及到兩個概念,一個是瀏覽器進程,一個是渲染進程。

#####回答二:

我認爲答案取決於我們在這裏討論的背景。

背景1:如果你正在和一個只知道網絡基本知識的朋友交談......

此上下文中的瀏覽器引擎是指爲您的瀏覽器提供內容並負責在屏幕上顯示內容的軟件。如果您在維基百科中搜索瀏覽器引擎,它會告訴您流行的瀏覽器引擎包括Webkit,Gecko,Trident等(https://en.wikipedia.org/wiki/Browser_engine)。

在這種情況下,估計很少有人知道有渲染引擎這個東西存在。

背景2:如果你正在和知道瀏覽器如何工作的朋友以及他們背後的所有瘋狂魔法交談......

此上下文中的瀏覽器引擎是指瀏覽器進程,主要負責管理所有I/o進程和顯示UI及跟渲染引擎通信等。

瀏覽器引擎:在UI和渲染引擎之間編組操作。

這也是正確的。如果你看一下Chromium的架構,你會發現瀏覽器進程/引擎使用渲染進程來協調頁面內容。

此上下文中的渲染引擎是指構造DOM,執行JavaScript和佈局網頁的程序,例如Webkit,Gecko,Trident。渲染引擎由兩個主要組件組成:WebCore包含核心佈局功能,JavaScriptCore包含JavaScript解釋器V8。

您的朋友似乎是專家,還必須瞭解渲染過程,該過程負責構建網頁。渲染引擎只是渲染過程中的關鍵部分。

下圖顯示了Chromium體系結構的高級體系結構概述(Google Chrome開源版本)。如果您想了解更多有關現代瀏覽器背後的魔力的信息,可以查看以下文章:https://medium.com/@zicodeng/explore-the-magic-behind-google-chrome-c3563dbd2739

瀏覽器進程/線程通信示意圖

二、渲染引擎(呈現引擎)

對文檔或其他資源進行解析後,渲染到瀏覽器窗口顯示。它是瀏覽器的核心部分。通常包含dom解析,css解析,生成render樹,layout/reflow,repaint,直至呈現給用戶。

三、內容8000個chunck(塊)

文中提到“內容的大小一般限制在 8000 個chunck塊以內”,解釋:Web服務器生成HTTP Response時無法在Header就確定消息大小的,這時一般來說服務器將不會提供Content-Length的頭信息,而採用Chunked編碼動態的提供body內容的長度。進行Chunked編碼傳輸的HTTP Response會在消息頭部設置: Transfer-Encoding: chunked

四、渲染過程

瀏覽器請求到HTML代碼後,在生成DOM的開始階段,並行發起css、圖片、js的請求。CSS文件下載完成後開始構建CSSOM。CSSOM構建完成後和DOM合併生成Render Tree(attachment)。瀏覽器計算出每個節點在屏幕的位置進行佈局。佈局完成後,通過顯卡,將內容畫到屏幕上。JS修改了DOM或者CSS屬性後,Layout和Paint也會被重複執行。圖片下載完成後也需要調用Layout和Paint來更新網頁。

五、dom+cssom -> render tree

從dom,cssom到渲染樹(frame樹)的過程不同的內核樹的概念不太一樣的,不過所做的工作都大同小異,就是計算形成若干能用於佈局的矩形盒子(寬度、高度和位置等幾何信息,該計算過程具體實現在layout或reflow階段),box模型。

Gecko 將視覺格式化元素組成的樹稱爲“框架樹”。每個元素都是一個框架。WebKit 使用的術語是“呈現樹”,它由“呈現對象”組成。對於元素的放置,WebKit 使用的術語是“佈局”,而 Gecko 稱之爲“重排”。對於連接 DOM 節點和可視化信息從而創建呈現樹的過程,WebKit 使用的術語是“附加”。有一個細微的非語義差別,就是 Gecko 在 HTML 與 DOM 樹之間還有一個稱爲“內容槽”的層,用於生成 DOM 元素。

六、樹及DOM節點

樹包含 DOM 節點,指的樹是由實現了某些DOM 接口的元素構成的。每個元素都有一條原型鏈,標準定義了每個DOM節點或元素必須要實現的DOM接口(屬性,方法,事件)。

七、添加defer,async的腳本預解析

通常html被解析的時候遇到js會阻塞執行,爲了優化體驗和速度,採用延遲或異步的方式,此時就存在了資源的預解析或異步執行的過程了。

八、共享樣式

共享樣式數據 WebKit 節點會引用樣式對象 (RenderStyle)。這些對象在某些情況下可以由不同節點共享。這些節點是同級關係,並且:

這些元素必須處於相同的鼠標狀態(例如,不允許其中一個是“:hover”狀態,而另一個不是) 任何元素都沒有 ID 標記名稱應匹配 類屬性應匹配 映射屬性的集合必須是完全相同的 鏈接狀態必須匹配 焦點狀態必須匹配 任何元素都不應受屬性選擇器的影響,這裏所說的“影響”是指在選擇器中的任何位置有任何使用了屬性選擇器的選擇器匹配 元素中不能有任何 inline 樣式屬性 不能使用任何同級選擇器。WebCore 在遇到任何同級選擇器時,只會引發一個全局開關,並停用整個文檔的樣式共享(如果存在)。這包括 + 選擇器以及 :first-child 和 :last-child 等選擇器。

代碼:

<div>
	<ul>
		<li>11</li>
		<li>22</li>
		<li>33</li>
	</ul>
</div>
div ul li{	color: red;	width: 100px;	height: 36px;
}

以上代碼就屬於符合要求的公共樣式。

Dirty 位系統

爲避免對所有細小更改都進行整體佈局,瀏覽器採用了一種“dirty 位”系統。如果某個呈現器發生了更改,或者將自身及其子代標註爲“dirty”,則需要進行佈局。

有兩種標記:“dirty”和“children are dirty”。“children are dirty”表示儘管呈現器自身沒有變化,但它至少有一個子代需要佈局。

在瀏覽器層面已經考慮到了因爲某些細小改動而發生全局重新計算和佈局的情況。所以虛擬DOM的出現只是爲了避免很多人爲的行爲導致的不必要重排,從而提升性能。

優化及虛擬DOM優化的基礎

如果佈局是由“大小調整”或呈現器的位置(而非大小)改變而觸發的,那麼可以從緩存中獲取呈現器的大小,而無需重新計算。 在某些情況下,只有一個子樹進行了修改,因此無需從根節點開始佈局。這適用於在本地進行更改而不影響周圍元素的情況,例如在文本字段中插入文本(否則每次鍵盤輸入都將觸發從根節點開始的佈局)。

Tali Garsiel and Paul Irish的這篇文章很長,也很有深度,適合反覆閱讀,幾次是很難完全理解的,而且涉及的知識面非常之廣,要徹底弄明白,至少也成了半個瀏覽器專家和排版專家了。不過這是有意義的。本文是針對其中部分疑點做了擴展閱讀,還有很多不明白的地方,之後抽時間深入涉獵。


作者:愛編程的光頭強(JM20110222)

版權聲明:轉載請註明出處,理解作者碼字的辛苦,謝謝!


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章