跳至主要内容

當你在瀏覽器輸入時發生了什麼

當朋友寄來了一個連結,於是我把它貼到chrome上並觀看他傳的連結是什麼。這件事是我們常做的,但有沒有思考過背後的原理,為什麼貼上網址,瀏覽器就能將網頁顯示出來呢。

當我們在瀏覽器輸入URL並按下Enter鍵時,背後發生了一系列複雜且高度協調的過程,這些過程涉及到瀏覽器、網絡協議、伺服器以及許多其他技術。這裡會簡單的介紹。

1. 瀏覽器接收URL並開啟一個新Process

瀏覽器是一個複雜的應用程式,本身由多個process和thread組成,並且透過這些process和thread協同工作以確保網頁的順利加載和顯示。當輸入URL並按下Enter鍵時,瀏覽器會啟動一個新的process來處理這次請求。這個新process專門負責網頁的載入和渲染,從而保證即使有一個process崩潰,其他網頁仍然可以正常運行。

2. 瀏覽器解析URL

該process將我們輸入的URL開始被解析為協定、網域名稱和路徑等資訊。以https://www.example.com/path為例:

  • 協定:https
  • 網域名稱:www.example.com
  • 路徑:/path

瀏覽器會根據這些資訊決定接下來的行動。協定決定了瀏覽器將使用哪種網絡協議(如HTTP或HTTPS),而網域名稱和路徑則幫助瀏覽器找到具體的資源。

URL的組成

URL(統一資源定位符)是一種標識網絡資源的方法,通常由以下部分組成:

  • 協定(protocol):如HTTP、HTTPS、FTP等,指定了如何訪問資源。
  • 網域名稱(domain name):如www.example.com,用於標識伺服器的地址。
  • 路徑(path):如/path,用於標識資源在伺服器上的位置。
  • 查詢參數(query parameters):如?key=value,用於傳遞附加資訊。
  • 片段識別符(fragment identifier):如#section,用於標識頁面內的某個部分。

3. DNS查詢

接下來,瀏覽器需要將網域名稱解析為對應的IP地址。這一過程稱為DNS查詢,主要分為以下幾步:

  • 瀏覽器首先查詢本地(Browser)的DNS緩存,看看是否有對應的IP地址。
  • 如果本地緩存中沒有,瀏覽器會請求作業系統(OS)進行DNS查詢。
  • 操作系統查詢本地的hosts文件,看是否有對應的IP地址。
  • 如果hosts文件中沒有,作業系統會向配置的DNS伺服器發送查詢請求。通常這些DNS伺服器是ISP(網際網路服務提供商)的伺服器。
  • DNS伺服器如果本身沒有記錄,會進行遞歸查詢,逐層向上查詢直至獲得結果。

DNS查詢的結果是一個IP地址,瀏覽器將使用這個IP地址與伺服器建立連線。

4. 建立TCP連線

有了IP地址後,瀏覽器需要與伺服器建立一個TCP連線。這一步包括TCP的三次握手過程:

  1. 瀏覽器向伺服器發送一個SYN(同步)包,請求建立連線。
  2. 伺服器收到SYN包後,回覆一個SYN-ACK(同步-確認)包,表示同意建立連線。
  3. 瀏覽器收到SYN-ACK包後,再回覆一個ACK(確認)包,完成連線建立。

這個過程確保了瀏覽器和伺服器之間的連線是可靠且雙向的。

5. 發送HTTPS協議請求

連線建立後,瀏覽器會向伺服器發送一個HTTPS請求。這個請求包括請求頭和請求體:

  • 請求頭包含了請求的基本資訊,如方法(GET、POST等)、目標URL、瀏覽器類型(User-Agent)等。
  • 請求體通常只在POST請求中包含,用於傳送數據。

HTTP(超文本傳輸協議)是用於傳輸超文本的協議,主要包括請求和回應兩部分:

  • HTTP請求:包括請求行(Request Line)、請求頭(Request Header)和請求體(Request Body)。請求行包含方法(如GET、POST)、URL和協議版本。請求頭包含一些元數據,如Host、User-Agent、Accept等。請求體包含實際的數據,通常用於POST請求。
  • HTTP回應:包括狀態行(Status Line)、回應頭(Response Header)和回應體(Response Body)。狀態行包含狀態碼(如200、404)和狀態描述。回應頭包含一些元數據,如Content-Type、Content-Length等。回應體包含實際的數據,如HTML、CSS、JavaScript等。

6. 伺服器處理請求並回應

伺服器接收到請求後,會進行處理並回應。回應包括狀態碼、回應頭和回應體:

  • 狀態碼表示請求的結果,如200(成功)、404(找不到資源)等。
  • 回應頭包含了回應的基本資訊,如內容類型(Content-Type)、內容長度(Content-Length)等。
  • 回應體包含了實際的數據,如HTML、CSS、JavaScript等。

7. 瀏覽器解析回應

瀏覽器接收到伺服器的回應後,會進行解析。這包括解析回應頭和回應體,並根據狀態碼判斷請求是否成功。如果成功,瀏覽器會開始處理回應體中的數據。

8. 解析、渲染和交互頁面

瀏覽器解析HTML文檔並生成DOM樹,解析CSS並生成CSSOM樹,然後將兩者合併生成渲染樹。接著,瀏覽器進行布局計算每個元素的位置和大小,然後進行繪製將元素顯示在屏幕上。這一過程包括以下步驟:

  1. 解析HTML:將HTML字符串分割成標記,然後生成DOM樹。
  2. 解析CSS:將CSS字符串分割成標記,然後生成CSSOM樹。
  3. 生成渲染樹:將DOM樹和CSSOM樹合併,生成渲染樹。
  4. 布局:計算每個元素的位置和大小。
  5. 繪製:將元素繪製到屏幕上。

8-1.解析

當瀏覽器接收到第一個數據片段,就會開始解析收到的訊息。解析(Parse)是指瀏覽器將接收到的數據轉換成DOM和CSSOM的過程。

瀏覽器接收到HTML文件後,會進行解析並生成DOM(Document Object Model)樹。解析過程如下:

  • 詞法分析:將HTML字符串分割成標記(tokens)。
  • 解析:將標記轉換為DOM樹中的節點。

接著,瀏覽器會解析CSS,生成CSSOM(CSS Object Model)樹。然後,瀏覽器將DOM樹和CSSOM樹合併,生成渲染樹(Render Tree)。渲染樹包含了顯示元素所需的所有資訊。

8-2.渲染

布局 Layout

也就是Reflow,瀏覽器將渲染樹做為輸入並計算各節點的大小、顏色、位置、形狀等資訊。負責篩選出顯示於畫面的元素,並將元素安排在畫面中的對應位置與大小。

觸發點:

  • DOM 元素改變
  • 布局相關樣式改變

影響成本高,涉及 DOM tree 的結構變化。

影響樣式:

  • 尺寸相關: width/height、padding/margin/border等
  • 位置相關: position、top/left/right/bottom、vertical-align等
  • 字體相關: font-size、font-family、text-align、line-height等
  • 其他: display、float、overflow等

繪製 Paint

也就是Repaint,針對各圖層擬定繪製指令列表,將元素的每個克見部分繪製到屏幕上。

這包括分層(Layer)、分塊(Tiling)、柵格化(Rasterization)。

  • 分層:瀏覽器會將DOM元素分配到不同的圖層,因為畫面上的元素可能會互相交疊,並且某些元素會有共同的CSS設置,或是變化時機相同的CSS樣式設置。
  • 分塊:每個圖層進一步分割成更小的塊,這樣可以更有效地管理內存和提高渲染效率。
  • 柵格化:將這些分塊轉換成像素,這個過程是由GPU加速完成的,能夠迅速生成最終的圖像。

觸發點:

  • Paint 相關樣式改變 影響樣式:
  • 顏色相關: color、background-color、outline-color等
  • 背景相關: background-image、background-position、background-size等
  • 輪廓相關: outline、outline-width、outline-style等
  • 邊界相關: border-radius、border-style等
  • 其他: visibility、box-shadow、text-decoration等

組合 Composition

當圖層都被柵格化後,組合執行緒(Compositor Thread)將柵格化後的圖層集結成一個組合幀(Compositor Frame),提交給GPU來繪製畫面。

觸發點:

  • 僅透明度和變形樣式改變 影響樣式:
  • opacity
  • transform

8-3.交互 Interactivity

一旦主thread繪製頁面完成,你會認為頁面已經“準備好了”,但事實並非如此。如果頁面包括延遲加載的JavaScript,並且僅在onload事件觸發後執行,那麼主thread可能會忙於執行腳本,無法用於滾動、觸摸和其他交互操作。

可交互時間(TTI)是測量從第一個請求到頁面可交互所用的時間——可交互是在首次內容繪製之後頁面在50毫秒內響應用戶的交互。如果主thread正在解析、編譯和執行JavaScript,則無法及時(小於50毫秒)響應用戶交互。

9. 連線結束

最後,瀏覽器和伺服器會中斷TCP連線,完成這次通信過程。這包括TCP的四次揮手過程:

  1. 瀏覽器發送一個FIN(終止)包,請求關閉連線。
  2. 伺服器收到FIN包後,回覆一個ACK(確認)包,確認已經收到請求。
  3. 伺服器再發送一個FIN包,請求關閉連線。
  4. 瀏覽器收到FIN包後,回覆一個ACK包,完成連線關閉。

總結

簡單來說,當我們在瀏覽器輸入URL並按下Enter鍵時,瀏覽器會啟動一個新的process來處理這次請求,解析URL並進行DNS查詢,然後與伺服器建立TCP連線,發送HTTP請求並接收回應,最後解析並渲染頁面。這一過程涉及到多種網絡協議和技術,如DNS、TCP、HTTP,以及瀏覽器內部的解析和渲染機制。