這篇文章的主要目的是用較爲簡單的術語來解釋一下,瀏覽器是怎樣一步步把HTML,CSS和JS變成你能看到(交互)的頁面css
知道瀏覽器是怎樣把網頁呈現給你的這個過程以後,就可以幫助你去優化你的網頁應用,從而提高速度和性能。html
瀏覽器如何呈現網站?node
我立刻就會闡述這個過程,可是首先,須要回顧一些基本概念。瀏覽器
一個網頁瀏覽器從遠程服務器上(或者本地文件)加載文件來顯示給你看,容許你進行操做。服務器
瀏覽器裏有一個瀏覽器引擎。網絡
不一樣的瀏覽器,都有一個瀏覽器引擎,基於獲取到的那個文件來知道怎樣顯示頁面。數據結構
瀏覽器引擎是主流瀏覽器的核心組件,不一樣瀏覽器製造商把他們的引擎起不一樣的名字。post
Firefox瀏覽器的引擎叫Gecko,Chrome的叫Blink(是Webkit的一個分支)。別由於這些名字感到困惑,它們只是名字而已,沒什麼大不了的。 更多瀏覽器引擎看這裏性能
在本文中,我可能會把「瀏覽器」和「瀏覽器引擎」互換着使用。不要有疑惑,咱們討論的核心就是瀏覽器引擎。優化
這裏不是一堂計算機網絡的課程,不過你應該記得數據是被看成「包(packets)」在網絡中傳輸的,以字節(bytes)大小爲單位。
我想說的關鍵是當你寫了HTML,CSS和JS後,想用瀏覽器來打開這個HTML文件,瀏覽器會從硬盤(網絡)上讀取原始字節(raw bytes)。
知道了麼?瀏覽器讀到的是原始字節數據,而不是真正你寫的代碼。瀏覽器獲取到了字節數據後,沒法用它來作任何事情。
這些字節數據必須轉換成可以理解的形式,這就是第一步。
瀏覽器須要用文檔對象模型(DOM)來工做。 那麼,DOM是怎麼來的? 首先,原始字節會轉成字符(characters)。這些字符就是你以前寫的代碼。這個轉換工做是由HTML的字符編碼器來完成的。 此時,瀏覽器從字節數據轉到了文件真實的字符。 字符內容不錯,可是他們還不是最終產物。 這些字符被進一步解析成標記(tokens)。
那麼,這些標記是什麼? 文件裏的那堆字符並不能讓瀏覽器來作些什麼。 若是沒有這步標記化轉換,這堆字符只是一堆無心義的文本內容(即html代碼),這並不能生成真正的網頁。當你把文件保存成.html
擴展名後,就是提醒瀏覽器用html
文檔的方式來解釋這個文件。瀏覽器來「解釋」這個文件第一步就是先解析它。 在這個解析過程當中,特別是在標記化中,(瀏覽器)會去考慮每一個開始和結束的html標籤(tags)。
解析器會去理解每一個在監控號裏的字符串,好比<html>
<p>
,並知道這些字符串的規則。好比,<a>
標記和<p>
具備不一樣的屬性。
從概念上來講,會把標記(tokens)看做是某種數據結構,它包含了某個html標籤的信息。實際上,一個html文件會被拆分紅一個個小的標記(tokens)。
標記(tokens)仍然不是咱們要的最後產物。
標記化結束後,這些標記還會被轉換成節點(nodes)。
你能夠把節點認爲是具備特定屬性的不一樣的對象。實際上,更好的解釋是把節點看作是文檔對象樹裏的一個單獨的實體。
節點(nodes)仍然不是最後結果。
好了,接下來是最後一點。
建立好節點後,這些節點會被鏈接成一棵樹狀的數據結構,也就是DOM樹。
DOM創建了父-子關係,兄弟關係等。
如今,這是咱們可使用的東西了。
通常,你不會用瀏覽器打開css和js文件來看網頁,通常會打開HTML文件,大多數狀況下打開的是index.html
。 這正是你這樣作的緣由:瀏覽器作任何事以前,必須先把html文件的原始數據轉換成DOM。
根據這個html文件,DOM構建過程可能都須要一些時間(不管大小)。
一個典型的html文件加入一個css連接,以下:
<!DOCTYPE html>
<html>
<head>
<link rel="stylesheet" type="text/css" media="screen" href="main.css" />
</head>
<body>
</body>
</html>
複製代碼
當瀏覽器引擎接收到原始數據並開始建立DOM的時候,也會發送請求去獲取main.css
樣式表。
瀏覽器開始解析html,一旦發現有link
標籤,同時就會去請求這個css
文件。
你可能猜到了,瀏覽器獲取到的CSS數據也是原始字節數據(無論從網絡仍是本地)。
可是這些CSS的原始數據是怎樣被處理的呢?
當瀏覽器獲取到CSS原始數據的時候,也會啓動一個相似處理HTML原數據的進程, 就像我上面所說的那樣,原始數據->字符->標記化->節點->樹。
這個樹是什麼?
許多人知道DOM樹,一樣的,也有一課叫作CSS對象模型的樹(CSSOM)。
你看到了,瀏覽器不能用HTML和CSS的原始數據來作事情。必然要通過轉換後變成瀏覽器可以是別的才能夠——也就是這些樹結構。
CSS裏有一種叫作級聯(Cascade)的機制,讓瀏覽器用來決定元素應該是採用哪一種樣式。
影響一個元素的樣式有:從父元素那裏繼承過來,或者設置在本身身上,所以CSSOM樹變得比較重要。
爲何?
這是由於瀏覽器必須遞歸遍歷CSS樹來肯定某個元素的樣式。
到如今爲止,咱們有了兩棵獨立的樹結構(DOM和CSSOM),彷佛絕不相關。
DOM包含了全部HTML元素的關係,而CSSOM包含了元素的樣式。
OK,瀏覽器如今把DOM和CSSOM組合成了渲染樹(render tree)。
渲染樹包含了全部的可見的DOM內容,以及不一樣節點的全部所須要的CSSOM信息。
注意,若是一個元素經過display:none;
方式隱藏的話,那它不會出如今渲染樹裏。 這個隱藏的元素在DOM樹裏,可是不在渲染樹裏。
由於渲染樹是從DOM和CSSOM合成出來的,因此它知道不包含這個隱藏的元素。
當渲染樹建好以後,瀏覽器開始下一步操做,迴流(layout)!
如今咱們已經有了能顯示在屏幕上的內容和樣式信息,可是咱們尚未渲染任何東西。
首先,瀏覽器須要計算每一個元素的準確大小以及位置。迴流就是經過DOM和CSSOM來執行所須要的計算。
「layout」,「reflow」,中文翻譯迴流。
經過DOM,CSSOM,以及迴流計算後,最後,瀏覽器就把各個節點畫到屏幕上了。