從輸入地址到頁面渲染,瀏覽器都做了什麼

單眼皮丶兒發表於2020-12-24

瀏覽器的主要功能

瀏覽器的主要功能是把你從伺服器請求到的網路資源呈現在瀏覽器視窗上,資源通常包含了HTML,PDF, 圖片等等,資源通常是由使用者指定的URI(Unifor resource Identifier 統一資源定位符)來定位的。

瀏覽器的主要組成部分:

此處引用了《瀏覽器是如何工作的》,很好的文章

使用者介面(The user interface) - 包含位址列、前進/後退按鈕、書籤等等。除了主要的視窗之外你所看到的就是請求的頁面。
瀏覽器引擎 - 查詢和操作渲染引擎的入口。
渲染引擎 - 負責呈現請求內容。例如請求內容是HTML, 渲染引擎負責解析HTML以及CSS,並且渲染解析後的內容到螢幕上。
網路連結 - 處理形如HTTP的網路請求。它有針對不同平臺的實現介面。
使用者介面的後臺處理程式(UI Backend) - 用於繪製類似於 bombo 盒子的小部件以及一些視窗,它丟擲了各個平臺通用的介面,它的底層是使用了作業系統的使用者介面方法。
Javascript 直譯器 - 用於解析和執行Javascrip程式碼。
資料儲存 - 這是一個持久層。瀏覽器需要在硬碟上儲存各種各樣的資料,比如coocies。HTNL5規範定義了'web database',針對瀏覽器的完整的資料庫(儘管比較輕量)片等等。

瀏覽器的多程式

瀏覽器是多程式的,有一個主控程式,負責協調控制各子程式,子程式包括:

  • 第三方外掛程式
  • GPU程式,用於3D繪製
  • 瀏覽器渲染程式,程式之間互不影響獨立控制、渲染、事件處理。每開一個tab就是開一個新的子程式,一個頁面崩潰了,瀏覽器不會崩。

當使用者輸入網址點選回車後:

  1. 瀏覽器開闢出一條執行緒接收url
  2. 在傳送請求前會判斷是否觸發快取,有快取讀取快取中的資料(後續介紹)
  3. 如果沒有快取,瀏覽器向 DNS域名伺服器查詢,把域名解析成IP找到相應主機(配置host可跳過dns域名解析,加速網頁渲染)
  4. 三次握手建立tcp連線,傳送http請求
  5. 伺服器響應請求,四次揮手返回資料並斷開連線。

瀏覽器獲取到 html後 

  1. 解析HTML,生成 DOM 樹
  2. 解析 CSS,生成 CSS 規則樹
  3. 合併 DOM 樹和 CSS 規則樹,生成 render 樹
  4. 佈局 render 樹(Layout/Reflow), 負責元素尺寸、位置的計算
  5. 繪製render樹(Paint),繪製頁面畫素資訊
  6. 瀏覽器將各層的資訊傳送給GPU,GPU會將各層合成(composite),顯示在螢幕上。

遇到外鏈時的處理 

當遇到外鏈資源時,會單獨開啟一個下載執行緒去下載資源(http1.1中是每一個資源的下載都要開啟一個http請求,對應一個tcp/ip連結)。

遇到css樣式資源

  • css下載非同步,不會阻塞構建DOM樹
  • 會阻塞渲染,因為構建render樹時會等到css下載解析完畢後進行(與瀏覽器優化有關,防止css規則不斷改變,避免了重複構建)
  • 有例外,媒體查詢(media query)宣告的css不會阻塞渲染

遇到js資源

  • 阻塞html的解析,遇到一個外鏈指令碼時,需等待js下載解析並執行後繼續解析html
  • 瀏覽器的優化,一般現代瀏覽器有優化,在指令碼阻塞時,也會繼續下載其他資源(有併發上限),雖然指令碼可以並行下載,解析過程仍然是阻塞的,也就是說必須這個指令碼執行完成後才會進行接下來的解析,並行下載只是一種優化而已。
  • defer與async,普通的指令碼是會阻塞瀏覽器解析的,但是加上這兩個屬性就變成了非同步了,可以等到解析完畢後再執行。
  • defer和async是有區別的,前者是延遲執行,後者是非同步執行。
    • async是非同步執行,非同步下載結束後就能執行,不確保執行順序,一定在onload前,不確定在DOMContentLoaded事件的前或後
    • defer是延遲執行,效果看起來像放到body後面一樣。

注:loaded 和 domcontentloaded

  • load 事件觸發時候,頁面上的DOM ,css,js,img都載入完了
  • DOMContentLoaded 僅當DOM載入完成,不包括css,圖片

遇到img圖片類資源

直接非同步下載,不阻塞解析,下載完成後直接用圖片替換原有src的地方(通常後於css,js檔案下載)

 

Tips:

  1. 瀏覽器對html的解析是自上而下的,且js的載入又會阻塞html的解析,所以如果我們把js放在header中,如果此指令碼操作了還未完成解析的dom,就會報錯,這也就是通常我們把script標籤置於body後的原因。
  2. DOM解析之後的動作:在這一步瀏覽器將會把文件標記為可互動的,同時開始解析在“defferred”模式下的scripts檔案(在文件解析完成之後將會被執行)。文件的狀態將會被修改為“complete”,同時觸發一個“load”事件。
  3. 綜上,我們能知道,如果想把script置於header中,最好用load函式包裹一下,即當頁面準備就緒後執行該指令碼。

window.οnlοad=function(){SomeJavaScriptCode};


 

相關文章