從年前就開始梳理瀏覽器的工做原理(主要對webkit內核的瀏覽器進行分析)到如今差很少快一個月了,本文意在幫助前端工程師瞭解瀏覽器的工做原理,並據此來優化咱們的網頁性能。
主要查閱了WebKit技術內幕、MDN、W3C等網站資料,下文中有若干圖片摘自於《WebKit技術內幕》,在此表示感謝。
本文略長,若有不適,實屬意外。若有不正確的地方,還望指正,畢竟傳播真理纔不會誤導其餘同窗,共同進步纔是目的。javascript
瀏覽器內核由渲染引擎和JS引擎組成,不一樣的瀏覽器、即便同一瀏覽器不一樣型號可能渲染引擎和JS引擎都不同。css
1)Trident渲染引擎 –> 老版本IE系列瀏覽器
2)Edge渲染引擎 -> Win10中IE瀏覽器
3)Gecko渲染引擎 –> Mozilla Firefox
4)Presto渲染引擎 –> Opera
5)KHTML渲染引擎 –> 早期的Safafi和Google Chrome
6)Webkit渲染引擎 -> 2001年後的Safari和Chrome以及國內的一些瀏覽器
7)Blink渲染引擎 -> 新版本的Chromium瀏覽器Google項目html
1)JScript引擎 –> IE系列瀏覽器
2)spiderMonkey引擎 –> Mozilla Firefox
3)V8引擎 –> Google Chrome
4)linear b/futhark引擎 –> Opera前端
爲你們提供兩個開發經常使用查詢網站:
該瀏覽器對html5的支持程度
不一樣與Can I usehtml5
上圖中虛線部分表示渲染引擎所提供的功能。
這裏渲染引擎包含了JavaScript引擎,許多時候二者都不太區分。
下面的內容大部分都是基於這張圖來分析的,咱們將逐步解釋從用戶輸入URL到頁面展現給用戶這個過程當中都發生了什麼?
咱們先了解網頁的基礎知識。java
html – 結構
css – 樣式
JavaScript – 行爲
還須要一些靜態資源:png、gif、webp、MP四、font、svg等等。
由上面幾部分就構成咱們的網頁。css3
讀者不要太關心上圖所標的順序,在某些時候可能會有出入。git
HTML解釋器:解釋HTML文本的解釋器,主要做用是將HTML文本解釋成DOM樹,DOM是一種文檔表示方法。
CSS解釋器:級聯樣式表的解釋器,它的做用是爲DOM中的各個元素對象計算出樣式信息,從而爲計算最後網頁的佈局提供基礎設施。
佈局:在DOM建立以後,webkit須要將其中的元素對象一樣式信息結合起來,計算它們的大小位置等佈局信息,造成一個可以表示這全部信息的內部比偶表示模型。
JavaScript引擎:使用JavaScript代碼能夠修改網頁的內容,也能修改CSS的信息,JavaScript引擎能過解釋JavaScript代碼並經過DOM接口和CSSOM接口來修改網頁內容和樣式信息,從而改變渲染結果。
繪圖:使用圖形庫將佈局計算後的各個網頁的節點繪製成圖像結果。github
PS:這些模塊依賴許多其餘基礎模塊,其中包括網絡、存儲、2D/3D圖形、音頻視頻和圖片解碼器等。這裏就不對基礎模塊作相應說明了。web
下面,我就逐個過程進行分析,我這裏省略一些非本文目的的過程,如DNS環節。
先來看看HTML解釋器工做原理
字節流(Bytes)–> 字符流(Characters)–> 詞語(Tokens)–> 節點 –> DOM樹
首先是字節流,通過解碼以後是字符流,而後經過詞法分析器會被解釋成詞語(Tokens),時候通過分析器構建成節點,最後這些節點被組建成一棵DOM樹。
詞法分析:HTMLTokenizer 類(做用是詞法分析,相似於狀態機),輸入的是字符串,輸出的是一個個的詞語。
XSSAuditor驗證詞語:XSSAuditor (驗證詞語流Token Stream)XSS指的是Cross Site Security,主要是針對安全方面的考慮。
詞語到節點:webkit用來構建DOM節點,這一步驟由HTMLDocumentParser 類調用 HTMLTreeBuilder 類的 constructTree的函數來實現。
節點到DOM樹:樹中的元素節點建立屬性節點等工做由HTMLConstructionSite類來完成,該類中包含一個 HTMLElementStack 做爲保存元素節點的棧。
JavaScript的執行:webkit將DOM樹建立過程當中須要執行得我Javascript代碼交由HTMLScriptRunner類來負責。
DOM的事件機制:webkit中用EventTarget類來表示DOM規範中Events部分定義的事件目標,Node 節點繼承自 EventTarget類,因此Node擁有EventTarget類的相關的方法。
這裏須要提一下W3C新規範,影子(Shadow)DOM
Shadow DOM API的 ShadowRoot接口是一個DOM子樹的根節點, 它與文檔的主DOM樹分開渲染。
MDN-影子節點
定義:Shadow DOM 爲Web組件中的 DOM和 CSS提供了封裝。Shadow DOM 使得這些東西與主文檔的DOM保持分離。
ShadowRoot 類繼承自 DocumentFragment 類。
PS:可使用document.createDocumentFragment 方法或者構造函數來建立一個空的 DocumentFragment.
先看看CSS怎麼和DOM結合展現頁面的呢?
css解釋器和規則匹配處於DOM樹創建以後,RenderObject樹創建以前,css解釋器解釋後的結果會保存起來,而後RenderObject樹基於該結果來進行規範匹配和佈局計算。
CSSOM視圖模塊(CSSOM View Module)定義了一些 API,Web 開發人員使用這些 API 能夠進行檢查,也能夠以編程方式更改文檔及其內容的視覺屬性,包括佈局框定位、視區寬度和元素滾動。
document.styleSheets 能夠查看當前頁面的StyleSheetList對象,每一個link、style都會產生 CSSStyleSheet 做爲 StyleSheetList對象的value。
DocumentStyleSheetCollection類(屬於Document類),該類包含了全部CSS樣式表,還包括了webkit的內部表示類CSSStyleSheet,它包含了CSS的href、類型、內容等信息。
CSS解釋過程:css字符串通過css解釋器處理後變成渲染引擎的內部規則的過程,使用CSSParser類來負責該過程。
在解釋網頁中自定義的CSS樣式以前,實際上webkit渲染引擎會爲每一個網頁設置一個默認樣式,這也是咱們爲何要重置瀏覽器樣式的根本緣由。
規則匹配:StyleResolver類爲DOM的元素節點匹配樣式,StyleResolver類根據元素的信息,例如標籤名、類別等,從樣式規則中查找最匹配的規則,而後將樣式信息保存到新建的RenderStyle對象中。最後,這些RenderStyle對象被RenderObject類所管理和使用。
其中,規則的匹配則是由ElementRuleCollector類來計算並得到,它根據元素的屬性等信息,並從DocumentRuleSets類中獲取規則集合,依次按照ID、CLASS、標籤等選擇器信息逐次匹配得到元素的樣式。
而後webkit對這些規則進行排序,對於該元素須要的樣式屬性,webkit選擇從高優先級規則中選取,並將樣式屬性值返回。
這裏,我引入一個不太相關的知識點,塊格式化上下文(Block Formatting Context,BFC) 是Web頁面的可視化CSS渲染的部分,是塊級盒佈局發生的區域,也是浮動元素與其餘元素交互的區域。
不太瞭解的同窗,請異步MDN-BFC
當webkit建立RenderObject對象以後,每一個對象是不知道本身的位置、大小等信息的,webkit根據盒模型來計算他們的位置、大小等信息的過程稱爲佈局計算/排版。
佈局計算分類:第一類是對整個RenderObject樹進行的計算;第二類是對RenderObject樹中某個子樹的計算,常見於文本元素或者overflow:auto塊的計算。
佈局計算:佈局計算是一個遞歸的過程,這是由於一個節點的大小一般須要先計算它的子節點的位置、大小等信息。
咱們常說的reflow和repaint。涉及到元素的幾何屬性改變會形成reflow會下降性能(transform、opacity等屬性不會形成reflow)。
擴展爲何說transform實現動畫較直接設置幾何屬性性能較好?
1.webkit渲染過程:style -> Layout(reflow發生在這) -> Paint(repaint發生在這) -> Composite,transform是位於’Composite(渲染層合併)‘,而width、left、margin等則是位於‘Layout(佈局)’層,這一定致使reflow。
2.現代瀏覽器針對transform等開啓GPU加速。
style -> Layout(reflow發生在這) -> Paint(repaint發生在這) -> Composite(transform發生在這個時候)
由這個過程咱們能夠看出,這也是爲何發生reflow一定會發生repaint的根本緣由。
CSS Animation性能優化
從重繪重排角度講解transform的動畫性能
RenderObject樹同其餘樹(如RenderLayer樹等),構成了webkit渲染的主要基礎設施。
一個RenderObject對象保存了爲繪製DOM節點所須要的各類信息,例如樣式佈局信息,通過webkit的處理以後,RenderObject對象知道如何繪製本身。
下列狀況會使DOM樹節點建立一個RenderObject對象(DOM和RenderObject並不是一一對應)。
1.DOM樹的document節點。
2.DOM樹種的可視節點,例如html、body、div等。而webkit不會爲非可視化節點建立RenderObject節點,例如meta、script。
3.某些狀況下webkit須要創建匿名的RenderObject節點,該節點不對應於DOM樹種的任何節點,而是webkit處理上的須要,典型的例子例如匿名的RenderBlock節點。
在html組建頁面結構時,webkit爲了提高網頁性能,會引入分層結構。
對於一個html文件webkit會爲某些元素和它的子節點創建新層,這樣webkit能夠單獨對某層操做提高性能,下列狀況會產生新層。
1.video標籤 – webkit在新層中有效的處理視頻解碼器和瀏覽器之間的交互和渲染問題。
2.div、p等普通標籤 – 涉及到3D變換時。
3.canvas標籤 – 複雜的2D和3D繪圖操做。
webkit會爲網頁的層次建立相應的RenderLayer對象。當某些類型RenderObject的節點或者某些css樣式的RenderObject節點出現的時候,webkit就會爲這些節點建立RenderLayer對象。
RenderLayer樹是基於RenderObject樹創建起來的一棵新樹。RenderLayer節點和RenderObject節點不是一一對應關係,而是一對多的關係。
哪些狀況下的RenderObject節點須要創建新的RenderLayer節點呢?
1.DOM樹的Document節點對應的RenderView節點。
2.DOM樹中的Document的子節點,也就是HTML節點對應RenderBlock節點。
3.顯式的制定css位置的RenderObject節點。
4.有透明效果的RenderObject節點。
5.節點有溢出(overflow)、alpha或者反射效果的RenderObject節點。
6.使用Canvas 2D和3D(WebGL)技術的RenderObject節點。
7.Video節點對應的RenderObject節點。
繪圖上下文(繪圖上下文能夠分紅兩種類型):
第一種是用來繪製2D圖形的上下文,稱之爲2D繪圖上下文(GraphicsContext)。
第二種是繪製3D圖形的上下文,稱之爲3D繪圖上下文(GraphicsContext3D)。
網頁的三種渲染方式:
1.軟件渲染(CPU內存)
2.使用軟件繪圖的合成化渲染(GPU內存)css3D、WebGL
3.硬件加速的合成化渲染(GPU內存)
在不須要硬件加速內容的時候(包括但不限於css3 3D變形、css3 3D變換、WebGL和視頻),webkit就可使用軟件渲染技術來完成頁面繪製。
對於每一個RenderObject對象,須要三個階段繪製本身:
第一階段是繪製該層中全部塊的背景和邊框。
第二階段是繪製浮動內容。
第三階段是前景(Foreground),也就是內容部分、輪廓、字體顏色、大小等(內嵌元素的背景、邊框等發生在這一階段)。
硬件加速技術是指使用GPU的硬件能力來幫助渲染網頁(GPU的做用主要是用來繪製3D圖形而且性能特別好)。
canvas開發,能夠將畫布分解爲更小的畫布,這樣在更新時只須要更新小畫布從而減小開銷。
css3 3D變形技術,它能過讓瀏覽器僅僅使用合成器來合成全部的層就能夠達到動畫效果(只觸發Composite而不用觸發style -> Layout(reflow發生在這) -> Paint)。
WebGL是Khronous組織提出的一套基於3D圖形定義的javascript接口。
它基於canvas元素,跟canvas2D不一樣的是,Web開發者可使用3D圖形接口來繪製各類3D圖形。
這裏包括3D變形和動畫。
webkit會創建一個新層來處理,從而提高性能。
推進JavaScript運行速度提升的利器JIT(Just-In-Time)。
JIT:就是代碼在目標平臺上運行的時候,實時的把代碼編譯爲目標機器上的機器碼。
編譯原理:
C++:源代碼 –> 抽象語法樹 –> 本地代碼
Java:源代碼 –> 抽象語法樹 –> 字節碼(跨平臺) –> JIT –> 本地代碼
經常使用的javascript引擎有v8和JavaScriptCore
工做原理
在js中,基本數據類型Boolean、Number、String、Null、Undefined、Symbol,其餘數據都是對象。
在V8中,數據的表示分紅兩個部分
第一部分是數據的實際內容,它們是變長的,並且內容的類型也不同,如String、對象等。
第二部分是數據的句柄,句柄的大小是固定的,句柄中包含指向數據的指針。
Handle:句柄類,主要用來管理基礎數據和對象,以便被垃圾回收器操做。
主要有兩個類型,一個Local類(繼承自Handle類),表示本地棧上的數據,因此比較輕量。
另外一個是Persistent類(繼承自Handle類)表示函數間的數據和對象訪問。
對於整形數據,由Handle自己來存儲,同時也爲了快速訪問。
其餘的數據都是從堆中申請內存來存儲它們,因爲其餘數據類型,受限於Handle的大小和變長等緣由,都存儲在堆中。
V8的延遲(deferred)特性:它使的許多javascript代碼的編譯直到運行的時候被調用到纔會發生,這樣能夠減小時間開銷。
機器語言(它是計算機惟一能直接執行的語言,電子計算機的機器指令是一列二進制數字。)
彙編語言 彙編指令是機器指令便於記憶的書寫格式,但他須要進過編譯器轉換爲機器語言,這樣機器才能執行。
時間間隔應該設置爲多少才合適呢。
跟屏幕的分辨率有關嗎(不一樣瀏覽器存在一個極小值)。
設置的時間會按照會準確執行嗎。
動畫會被平滑地顯示效果嗎。
回調函數時複雜的好仍是簡單的好呢。
window.requestAnimationFrame
在早期的瀏覽器能力十分有限,Web前端開發者們但願可以經過一些機制來擴展瀏覽器的能力(插件機制如flash插件)。
NPAPI是當今最流行的插件架構,幾乎全部瀏覽器都支持,不過存在很大的安全隱患,插件能夠竊取系統底層權限,發起惡意攻擊。
2010年,Google開發了新的PPAPI,將外掛插件所有放到沙盒裏運行,2012年Windows、Mac版本的Chrome瀏覽器前後升級了PPAPI Flash Player,並但願今年末以前完全淘汰NPAPI。
經過以下url參看當前chrome瀏覽器安裝的extensions
chrome://extensions/
WebRTC實現了基於網頁的視頻會議,標準是WHATWG 協議,目的是經過瀏覽器提供簡單的javascript就能夠達到實時通信(Real-Time Communications (RTC))能力。
MDN-WebRTC
最重要的方法:navigator.mediaDevices.getUserMedia(constraints)
還有Video、Audio等。
第一部分是網頁的安全,包括可是不限於網頁數據安全傳輸、跨域訪問、用戶數據安全等。
第二部分是瀏覽器的安全,具體是指雖然網頁或者Javascript代碼有一些安全問題或者存在安全漏洞,瀏覽器也可以在運行它們的時候保證吱聲的安全,不受到攻擊從而泄漏數據或者使系統遭受破壞。
安全模型基礎:
域(Same Origin Policy)XMLHttpRequest、cookie的讀寫、DOM對象操做等。
XSS(Cross Site Scripting)執行跨域的js腳本代碼。開發者能夠將用戶輸入的數據進行字符轉換來避免。webkit經過XSSAuditor對象幫咱們過濾(默認開啓)。
CSP (Content-Security-Policy)HTTP首部字段,內容安全策略(CSP)用於檢測和減輕用於 Web 站點的特定類型的攻擊,例如 XSS 和數據注入等。
CORS(Cross Origin Resource Sharing)跨域資源共享標準新增了一組 HTTP 首部字段,容許服務器聲明哪些源站有權限訪問哪些資源。
具體服務端代碼設置
// 請求頭
header('Access-Control-Allow-Origin: http://arunranga.com'); //
header('Access-Control-Allow-Methods: POST, GET, OPTIONS');
header('Access-Control-Allow-Headers: X-PINGARUNER');
// 響應頭
Access-Control-Allow-Origin、
Access-Control-Allow-Credentials、
Access-Control-Allow-Headers、
Access-Control-Expose-Headers、
Access-Control-Allow-Methods、
Access-Control-Max-Age複製代碼
Cross Document Messaging 經過 window.postMessage 和 message 事件來通訊。
HTTPS(安全傳輸協議)
SPDY(讀做「SPeeDY」)是Google開發的基於TCP的應用層協議,用以最小化網絡延遲,提高網絡速度,優化用戶的網絡使用體驗。 SPDY核心思想爲多路複用。
QUIC(Quick UDP Internet Connection)是谷歌制定的一種基於UDP的低時延的互聯網傳輸層協議。
CSP定義了網頁自身可以訪問的某些域和資源。
CORS定義一個網頁如何才能訪問被同源策略禁止的跨域資源,並規定了二者交互的協議和方式。
瀏覽器的沙箱模型是利用系統提供的安全技術,讓網頁在執行過程當中不會修改操做系統或者是訪問系統中的隱私數據,而須要訪問系統資源或者說是系統調用的時候,經過一個代理機制來完成。
一下url直接輸入在瀏覽器中,enter便可
URL | 做用 |
---|---|
chrome://inspect | 移動端網頁調試 |
chrome://net-internals | net-internals是一套工具集合,用於幫助診斷網絡請求與訪問方面的問題,它經過監聽和蒐集 DNS,Sockets,SPDY,Caches等事件與數據來向開發者反饋各類網絡請求的過程、狀態以及可能產生影響的因素。如,查看DNS主機解析緩存chrome://net-internals/#dns |
chrome://view-http-cache/ | 查看內部存儲內容及其詳情 |
chrome://downloads/ | 下載內容管理,其快捷鍵是Ctrl+J |
chrome://extensions/ | 擴展管理 |
chrome://bookmarks/ | 書籤管理 |
chrome://history | 訪問歷史管理 |
chrome://restart | 重啓chrome瀏覽器 |
chrome://apps | chrome網上應用店 |
chrome://flags/ | 新特性管理 |
chrome://dns | 查看DNS預取命名(從超連接等處來預測) |
chrome://quota-internals | 查看瀏覽器所使用磁盤空間配額 |
chrome://settings | 瀏覽器的設置 |
chrome://sync-internals | 查看chrome 的同步狀態 |
chrome://about/ | 查看全部chrome命令 |