URL
到頁面渲染的過程從輸入URL
到頁面渲染須要Chrome
瀏覽器的多個進程配合,因此咱們先來談談現階段Chrome
瀏覽器的多進程架構。css
Chrome
架構目前Chrome
採用的是多進程的架構模式,可分爲主要的五類進程,分別是:瀏覽器(Browser
)主進程、 GPU
進程、網絡(NetWork
)進程、多個渲染進程和多個插件進程;html
HTML
、CSS
和 JavaScript
轉換爲用戶能夠與之交互的網頁,排版引擎Blink
和JavaScript
引擎V8
都是運行在該進程中,默認狀況下,Chrome
會爲每一個Tab
標籤建立一個渲染進程。出於安全考慮,渲染進程都是運行在沙箱模式下。GPU
進程。其實,Chrome
剛開始發佈的時候是沒有GPU
進程的。而GPU
的使用初衷是爲了實現3D CSS
的效果,只是隨後網頁、Chrome
的UI
界面都選擇採用GPU
來繪製,這使得GPU
成爲瀏覽器廣泛的需求。最後,Chrome
在其多進程架構上也引入了GPU
進程。瞭解了Chrome
的多進程架構,就可以從宏觀上理解從輸入URL
到頁面渲染的過程了,這個過程主要分爲導航階段和渲染階段。webpack
URL
url
,組裝協議,構成完整的url
,這時候有兩種狀況:
URL
。URL
:地址欄會根據規則,給這段內容加上協議,合成爲完整的URL
;IPC
)把url
請求發送給網絡進程;URL
請求過程url
請求後檢查本地緩存是否緩存了該請求資源,若是有則將該資源返回給瀏覽器進程;這裏涉及到瀏覽器與HTTP協議的緩存策略問題,有興趣的能夠看這篇文章:詳解HTTP協議web
四、準備IP
地址和端口:進行DNS
解析時先查找緩存,沒有再使用DNS
服務器解析,查找順序爲:chrome
hosts
文件;ISP DNS
緩存;DNS
遞歸查詢(本地DNS
服務器 -> 權限DNS
服務器 -> 頂級DNS
服務器 -> 13
臺根DNS
服務器)五、等待TCP
隊列:瀏覽器會爲每一個域名最多維護6
個TCP
鏈接,若是發起一個HTTP
請求時,這 6
個 TCP
鏈接都處於忙碌狀態,那麼這個請求就會處於排隊狀態;解決方案:瀏覽器
CDN
)域名下面。HTTP2
,就沒有6
個TCP
鏈接的限制了;六、經過三次握手創建TCP
鏈接:緩存
TCP
首部中:標誌位:同步SYN
爲1
,表示這是一個請求創建鏈接的數據包;序號Seq=x
,x
爲所傳送數據的第一個字節的序號,隨後進入SYN-SENT
狀態;標誌位值爲
1
表示該標誌位有效。安全
SYN
標誌位判斷爲創建鏈接的請求,隨後返回一個確認數據包,其中標誌位SYN=1
,ACK=1
,序號seq=y
,確認號ack=x + 1
表示收到了客戶端傳輸過來的x
字節數據,並但願下次從x+1
個字節開始傳,並進入SYN-RCVD
狀態;這裏要區分標誌位
ACK
和確認號ack
;服務器
ACK=1
,序號seq=x+1
,確認號ack=y+1
,隨後進入ESTABLISHED
狀態;服務器端收到後,也進入ESTABLISHED
狀態,由此成功創建了TCP
鏈接,能夠開始數據傳送;網絡
若是沒有最後一個數據包確認(第三次握手),
A
先發出一個創建鏈接的請求數據包,因爲網絡緣由繞遠路了。A
通過設定的超時時間後還未收到B
的確認數據包。因而發出第二個創建鏈接的請求數據包,此次網路通暢,
B
的確認數據包也很快就到達A
。因而A
與B
開始傳輸數據;過了一會
A
第一次發出的創建鏈接的請求數據包到達了B
,B
覺得是再次創建鏈接,因此又發出一個確認數據包。因爲A已經收到了一個確認數據包,因此會忽略B
發來的第二個確認數據包,可是B
發出確認數據包以後就要一直等待A
的回覆,而A
永遠也不會回覆。由此形成服務器資源浪費,這種狀況多了
B
計算機可能就中止響應了。
七、構建併發送HTTP
請求信息;
八、服務器端處理請求;
九、客戶端處理響應,首先檢查服務器響應報文的狀態碼:
301/302
表示服務器已更換域名須要重定向,這時網絡進程會從響應頭的Location
字段裏面讀取重定向的地址,而後再發起新的HTTP
或者HTTPS
請求,跳回第4
步。200
,就檢查Content-Type
字段,值爲text/html
說明是HTML
文檔,是application/octet-stream
說明是文件下載;Conection
不是Keep-Alive
時,即不爲TCP
長鏈接時,經過四次揮手斷開TCP
鏈接:FIN=1
,序號位seq=u
,並中止發送數據;ACK=1
,序號seq=v
,確認號ack=u+1
的數據包;FIN=1
,標誌位ACK=1
,序號seq=w
,確認號ack=u+1
;ACK=1
,序號seq=u+1
,確認號ack=w+1
的數據包。由此經過四次揮手斷開TCP
鏈接。
詳細過程參見:詳解TCP鏈接的「三次握手」與「四次揮手」(上)
FIN
釋放鏈接報文與ACK
確認接收報文須要分兩次傳輸,即第二次和第三次"揮手";url
是否與以前打開了渲染進程的頁面的根域名相同,若是相同,則複用原來的進程,若是不一樣,則開啓新的渲染進程;url
、前進後退的歷史狀態、更新web
頁面在渲染階段經過渲染流水線在渲染進程的主線程和合成線程配合下,完成頁面的渲染;
渲染進程中的主線程部分
DOM
樹1三、先將請求回來的數據解壓,隨後HTML
解析器將其中的HTML
字節流經過分詞器拆分爲一個個Token
,而後生成節點Node
,最後解析成瀏覽器識別的DOM
樹結構。
能夠經過Chrome
調試工具的Console
選項打開控制檯輸入document
查看DOM
樹;
渲染引擎還有一個安全檢查模塊叫
XSSAuditor
,是用來檢測詞法安全的。在分詞器解析出來Token
以後,它會檢測這些模塊是否安全,好比是否引用了外部腳本,是否符合CSP
規範,是否存在跨站點請求等。若是出現不符合規範的內容,XSSAuditor
會對該腳本或者下載任務進行攔截。
首次解析HTML
時渲染進程會開啓一個預解析線程,遇到HTML
文檔中內嵌的JavaScript
和CSS
外部引用就會同步提早下載這些文件,下載時間以最後下載完的文件爲準。
CSSOM
1四、CSS
解析器將CSS
轉換爲瀏覽器能識別的styleSheets
也就是CSSOM
:能夠經過控制檯輸入document.styleSheets
查看;
這裏要考慮一下阻塞的問題,因爲JavaScript
有修改CSS
和HTML
的能力,因此,須要先等到 CSS
文件下載完成並生成 CSSOM
,而後再執行 JavaScript
腳本,最後再繼續構建 DOM
。因爲這種阻塞,致使了解析白屏;
優化方案:
- 移除
js
和css
的文件下載:經過內聯JavaScript
、內聯CSS
;- 儘可能減小文件大小:如經過
webpack
等工具移除沒必要要的註釋,並壓縮js
文件;- 將不進行
DOM
操做或CSS
樣式修改的JavaScript
標記上sync
或者defer
異步引入;- 使用媒體查詢屬性:將大的
CSS
文件拆分紅多個不一樣用途的CSS
文件,只有在特定的場景下才會加載特定的CSS
文件。
能夠經過瀏覽器調試工具的Network
面板中的DOMContentLoaded
查看最後生成DOM
樹所需的時間;
em
轉換爲px
,color
轉換爲rgb
;DOM
樹中每一個節點的具體樣式,這裏遵循CSS
的繼承和層疊規則;能夠經過Chrome
調試工具的Elements
選項的Computed
查看某一標籤的最終樣式;1七、建立佈局樹,遍歷DOM
樹中的全部節點,去掉全部隱藏的節點(好比head
,添加了display:none
的節點),只在佈局樹中保留可見的節點。
1八、計算佈局樹中節點的座標位置(較複雜,這裏不展開);
Layer Tree
),能夠經過Chrome
調試工具的Layer
選項查看。分層樹中每個節點都直接或間接的屬於一個圖層(若是一個節點沒有對應的層,那麼這個節點就從屬於父節點的圖層)渲染進程中的合成線程部分
2一、合成線程將圖層切分紅大小固定的圖塊(256x256
或者512x512
)而後優先繪製靠近視口的圖塊,這樣就能夠大大加速頁面的顯示速度;
GPU
進程GPU
來加速生成,使用GPU
生成位圖的過程叫快速柵格化,或者GPU
柵格化,生成的位圖被保存在GPU
內存中。DrawQuad
」,而後將該命令提交給瀏覽器進程。注意了:合成的過程是在渲染進程的合成線程中完成的,不會影響到渲染進程的主線程執行;
viz
的組件,用來接收合成線程發過來的DrawQuad
命令,而後根據DrawQuad
命令,將其頁面內容繪製到內存中,最後再將內存顯示在屏幕上。到這裏,通過這一系列的階段,編寫好的HTML
、CSS
、JavaScript
等文件,通過瀏覽器就會顯示出漂亮的頁面了。
參考資料:瀏覽器工做原理與實踐