当我们在浏览器中输入一个URL后,发生了什么?
原文發表在我的個人博客: kmknkk.xin
圖源:知乎-張秋怡
瀏覽器解析并查詢緩存
DNS查詢
-
DNS查詢順序如下,若其中一步成功則直接跳到建立鏈接部分:
- 瀏覽器自身DNS
- 操作系統DNS
- 本地hosts文件
- 向域名服務器發送請求
建立鏈接
-
TCP三次握手(three-way handshaking)
- 發送方:SYN(synchronize)
- 接收方:SYN/ACK(acknowledgement),確認信息傳達
- 發送方:ACK - 確認接收方在線可收消息,握手結束
- Accept
TCP三次握手的的好處在于:發送方可以確認接收方仍然在線,不會因為白發送而浪費資源。
發送HTTP請求
-
報文首部(GET /index.html HTTP/1.1)
- 方法
- URL
- HTTP版本
- 空行(CR+LF)
- 報文主體
注意:
1.HTTP是無連接、無狀態的,即HTTP在傳輸完成后就會斷開(HTTP1.1以前),并且不會記錄訪問者的狀態。
從HTTP/1.1開始才默認支持持久化連接,即通信一次以后連接不中斷,HTTP/1.0需要手動設置:keep-alive。
正常來說,HTTP請求、響應方式為每請求一次就響應一次:
請求1 -> 響應1 -> 請求2 -> 響應2 -> 請求3 -> 響應3若采用持久連接請求管線化方式:
請求1 -> 請求2 -> 請求3 -> 響應1 -> 響應2 -> 響應3使用管線化的條件:
- 服務端需要支持管線化
- 只有GET和HEAD可以進行管線化,POST請求有所限制
- 管線化不會影響響應到來的順序
2.關于CR(Carriage Return,回車)和LF(Line Feed,換行)
Dos和Windows采用CR/LF表示下一行UNIX/Linux采用LF表示下一行
MAC OS系統則采用CR表示下一行
服務器發送響應
-
報文首部(HTTP/1.1 200 OK)
- HTTP版本
- 響應狀態碼
- 狀態碼信息
- 空行(CR+LF)
- 報文主體
客戶端收到頁面,瀏覽器渲染頁面
執行以下過程:
解析HTML
- 根據DOCTYPE來確定文檔類型(最常見的就是HTML5,注意如果是HTML4的話有嚴格和寬松模式之分)
- 構建DOM樹(根據HTML構建類似于二叉樹的結構樹)
-
下載資源
- CSS - 構建CSSOM樹
- js - 等下下載并執行后解析
瀏覽器渲染
在聊瀏覽器渲染之前,我們先明確一個概念: 事實上,我們看到的頁面并不是直觀所見的一層圖頁,而是由許多DOM元素渲染層(Layers)組成的,如下圖。
頁面的渲染過程
所以一個的頁面的渲染過程由如下幾步構成:
- 構建渲染樹(Render Tree): 根據DOM和CSSOM樹渲染,不可見元素不被會渲染
- 布局(layout): CPU根據渲染樹布局計算元素的具體位置和大小,轉換成絕對像素,并且根據樣式,分割成多個獨立的渲染層(Layers),將每一層對應到位圖中
- 繪制(Paint): GPU根據每個渲染層(Layers)的位圖繪制每個點,即像素填充,并且將所以渲染層緩存,如果下次頁面變動但是渲染層沒變就不會觸發重繪。
- 層級合成(Compositing): 顧名思義,即處理多層渲染層之間的關系,將其合成為一個完整的頁面。
重繪和重排
重繪(repaint):
- 元素視覺表現屬性被改變即觸發重繪,如改變visibility,color等,不會影響到dom結構
reflow(重排):
- 與repaint區別就是:所有影響dom的元素布局的事件都會觸發重排。同時也會觸發repaint。
- 這種開銷是非常昂貴的,導致性能下降是必然的,頁面元素越多效果越明顯。
reflow常見情況:
- 增刪改DOM節點
- 移動DOM的位置或是動畫顯示(所以盡量用canvas來做動畫)
- 修改width、display等CSS樣式
- resize窗口或是滾動的時候
- 修改網頁默認字體(不建議)
- display:none會觸發reflow和repaint,而visibility:hidden只會產生repaint
顯而易見,要提高頁面性能,首要目標就是減少重繪重排,具體方法包括當不限于以下幾種:
- 壓縮DOM深度,以免內層元素改變而導致多個外層都改變。
- 對于沒用的元素,盡量設置為display:none,減輕繪制壓力。
- 在對DOM進行大量元素操作時,我們可以使用利用DocumentFragment對象進行操作,最后再一次性裝載進DOM結構中。
- 指定img的大小:由于img是內聯元素,所以在加載后會改變寬高,嚴重的會導致整個頁面重排,所以最好在渲染前就設置好其寬高,或者讓其脫離文檔流。
DOM渲染層(Layers)與GPU硬件加速
知道了瀏覽器頁面的渲染合成過程后,我們不難得出一個結論:
如果我們把會發生大量重繪重排的元素提取出來,單獨觸發一個渲染層(Layer),就不會把其他元素一起帶著重繪,這會大大提高頁面性能。那么如何觸發渲染層,讓GPU來加速繪制呢?最簡單的方法有以下三種:
will-change: transform; will-change: opacity; transform: translateZ(0);PS:使用Layers來觸發GPU加速(硬件加速)也會帶來負面影響,如電量損失過快、占用內存和GPU等。所以在使用中要注意不能濫用,在常觸發重繪和重排的元素上使用即可。
總結
以上是生活随笔為你收集整理的当我们在浏览器中输入一个URL后,发生了什么?的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 紫书 习题 10-7 UVa 10539
- 下一篇: 开通博客啦