前端開發者應該明白的瀏覽器工作原理

banggan發表於2019-02-20

原文地址:banggan.github.io/2019/02/20/…

前言

作為前端開發,我們平常跟瀏覽器打交道的時間也是最多的。在前端面試中,一個較為經典的問題:在瀏覽器地址中輸入url地址,敲回車,發生了什麼?瀏覽器究竟做了什麼?相信很多人腦海裡都會出現個大概的輪廓,可是一到細化具體的過程就答不上來。那麼,作為前端開發者,應該從哪些方面延伸來回答這個問題呢?

瀏覽器工作流程

對於瀏覽器來說,當在位址列輸入url地址,瀏覽器所做的事情就是把一個url變成一個在螢幕上顯示的網頁,大致的過程是這樣的:

在這裡插入圖片描述
從HTTP請求回來 ,產生流式的資料,DOM的構建、CSS計算、渲染、繪製,都是儘可能的流式處理前一步的產出,不需要等待上一步完全接受才開始處理,所以我們在瀏覽網頁的時候,才會逐步出現頁面。

  1. 瀏覽器接受url開啟一個網路請求執行緒
  2. 瀏覽器發出一個完整的http請求
  3. 伺服器接收請求到後臺接收請求
  4. 使用http請求請求頁面
  5. 把請求回來的html程式碼解析成DOM樹
  6. CSS的視覺化格式模型解析
  7. 根據CSS屬性對元素進行渲染,得到記憶體中的點陣圖
  8. 對點陣圖的合成
  9. 繪製頁面

瀏覽器接受url開啟網路請求執行緒

第一點主要涉及的是瀏覽器的程式、執行緒模型以及JS的執行機制:

多程式的瀏覽器

大多數瀏覽器是多程式的,有一個主控程式,以及每一個tab頁面都會新開一個程式(某些情況下多個tab會合並程式) 程式可能包括主控程式,外掛程式,GPU,tab頁(瀏覽器核心)等等。

  • Browser程式:瀏覽器的主程式(負責協調、主控),只有一個
  • 第三方外掛程式:每種型別的外掛對應一個程式,僅當使用該外掛時才建立
  • GPU程式:最多一個,用於3D繪製
  • 瀏覽器渲染程式(核心):預設每個Tab頁面一個程式,互不影響,控制頁面渲染,指令碼執行,事件處理等(有時候會優化,如多個空白tab會合併成一個程式)
多執行緒的瀏覽器核心

每一個tab頁面可以看作是瀏覽器核心程式,然後這個程式是多執行緒的,它有幾大類子執行緒:

  • GUI執行緒
  • JS引擎執行緒
  • 事件觸發執行緒
  • 定時器執行緒
  • 網路請求執行緒

開啟網路執行緒發出一個完整的http請求

該部分主要包括:dns查詢、tcp/ip請求構建、五層因特網等內容

DNS查詢

如果輸入的是域名,需要進行dns解析成IP,大致流程:

  • 如果瀏覽器有快取,直接使用瀏覽器快取,否則使用本機快取,再沒有的話就是用host
  • 如果本地沒有,就向dns域名伺服器查詢(當然,中間可能還會經過路由,也有快取等),查詢到對應的IP。
tcp/ip請求

這裡的tcp/ip請求需要了解3次握手規則建立連線以及斷開連線時的四次揮手,可以參考之前的部落格:blog.csdn.net/bangbanggan…

五層因特網協議

其實這個概念挺難記全的,記不全沒關係,但是要有一個整體概念。 其實就是一個概念:從客戶端發出http請求到伺服器接收,中間會經過一系列的流程。 簡括就是:從應用層的傳送http請求,到傳輸層通過三次握手建立tcp/ip連線,再到網路層的ip定址,再到資料鏈路層的封裝成幀,最後到物理層的利用物理介質傳輸。 當然,服務端的接收就是反過來的步驟。 五層因特爾協議棧其實就是: 1.應用層(dns,http) 2.傳輸層(tcp,udp) 建立tcp連線(三次握手) 3.網路層(IP,ARP) IP定址 4.資料鏈路層(PPP) 5.物理層 OSI七層框架: 物理層、 資料鏈路層、 網路層、 傳輸層、 會話層、 表示層、 應用層。 表示層:主要處理兩個通訊系統中交換資訊的表示方式,包括資料格式交換,資料加密與解密,資料壓縮與終端型別轉換等 會話層:它具體管理不同使用者和程式之間的對話,如控制登陸和登出過程

網路通訊HTTP協議

HTTP協議是基於TCP協議出現的,在TCP的基礎上規定了Request-Response的模型,決定了通訊必須由瀏覽器端發起的,首先來了解下HTTP協議的格式:

HTTP協議格式

HTTP協議大致可以分成以下部分:其中path是請求路徑、version是固定的字串,依次介紹下面的每個部分:

在這裡插入圖片描述

HTTP Method 請求方法

在requestline裡面的方法部分,表示HTTP的操作型別,常見的幾種請求方法如下:

  • GET:瀏覽器通過地址訪問頁面均屬於get請求
  • POST:常見的表單提交
  • HEAD :跟get類似,區別在於只返回請求頭
  • PUT:表示新增資源
  • DELETE:表示刪除資源
  • CONNECT: 多用於HTTPS和WebSocket
  • OPTIONS
  • TRACE
HTTP Status code狀態碼

常見的狀態碼有以下幾種:

  • 1xx:臨時迴應
  • 2xx:請求成功,如200
  • 3xx:請求目標有變化,如301和302表示臨時和永久重定向,304表示客戶端沒有更新內容
  • 4xx;請求錯誤,如403無許可權,404訪問的資源不存在
  • 5xx:服務端錯誤,如500服務端錯誤,503服務端暫時錯誤等

在前端開發中,最熟悉的系列無非是大家都喜歡的200請求成功的標誌,在面試中,問得較多的是304快取問題和301、302重定向的問題。

HTTP HEAD(HTTP頭)

HTTP頭可以看做是一個鍵值對,在HTTP標準中,Request Header如下圖:

在這裡插入圖片描述
Response Header如下圖:
在這裡插入圖片描述
在實際的開發中,完整的列表可以參考rfc2616標準。

HTTP Request Body

HTTP請求的body主要用於表單的提交,常見的body格式:

  • application/json
  • application/x-www-form-urlencoded:使用form標籤提交的html請求,預設產生
  • multipart/form-data:當有檔案上傳時,使用的格式
HTTPS

HTTPS在HTTP的基礎上增加了兩個作用,一是確定請求的目標服務端身份,二是保證傳輸的資料不會被篡改或者竊聽,該協議使用加密通道來傳輸HTTP內容,所以首先需要與服務端簡歷TLS加密通道。可以在此處檢視詳情:tools.ietf.org/html/rfc281…

HTTP2

HTTP2是HTTP1.1的升級版,有兩大改進:一是支援服務端推送,二是支援TCP連結複用:則使用同一個TCP連結來傳輸多個HTTP請求。詳情見:tools.ietf.org/html/rfc754…

構建DOM樹

當瀏覽器使用HTTP向服務端請求頁面後,那麼如何去解析請求回來的HTML程式碼、構建DOM樹呢?

在這裡插入圖片描述

字元流如何解析成詞

首先瀏覽器讀取獲取的HTML,根據指定的檔案編碼方式如UTF-8轉換為字元流,再將字串轉換為詞Token。那什麼是詞?詞是編譯原理中的最小單元,如標籤開始、屬性、標籤結束、註釋、CDATA節點。Token會標識出當前Token的種類。舉個列子: <p class="a" >hello</p>

這裡就可以拆分成<p(p標籤的開始)、class="a"(屬性)、>(p標籤的結束)、hello(文字)、</p>(結束標籤)

構建DOM樹

接下來就是將詞變成DOM樹。在構建DOM樹時,是一邊生成Token一邊消耗Token來生成節點的。

<html>
<head>
    <title>Web page parsing</title>
</head>
<body>
    <div>
        <h1>Web page parsing</h1>
        <p>This is an example Web page.</p>
    </div>
</body>
</html>
複製程式碼

構建的DOM樹:

在這裡插入圖片描述

構建CSSOM

在構建完DOM樹,當前的物件只包含節點和屬性,沒有任何樣式資訊,那麼瀏覽器是如何給DOM樹新增CSS屬性呢?我們知道瀏覽器是流式的處理整個過程,我們拿到DOM樹構造好的元素,依次去檢查他匹配的規則,再根據規則的優先順序,做覆蓋和調整。

構建渲染樹

當CSSOM樹和DOM樹都得到之後,將兩個樹進行合併就得到了渲染樹:

在這裡插入圖片描述

佈局與繪製

當瀏覽器生成渲染樹以後,就會根據渲染樹來進行佈局。在這個過程中,每一個元素都要要弄清楚各個節點在頁面中的確切位置和大小,把對應的盒變為相應的點陣圖。一個元素可能對應多個盒(如內聯元素,可能被分成多行)每一個盒都對應著一個點陣圖。合成把部分點陣圖合成變成合成層。最終的繪製過程就是把點陣圖合成層繪製到螢幕上。 這裡提一個常見的問題,重繪和迴流?具體的相關知識參考:segmentfault.com/a/119000001…

總結

瀏覽器的工作流程大致就是:

構建DOM樹-構建CSSOM-構建渲染樹-佈局-繪製

相關文章