在開始之前需要先大致了解 URL 以及 IP 位址之間的關係。
網絡上的任何資源需要透過 網址(URL, Uniform Resource Locator) 來訪問。以生活中的例子來比喻的話網址就像是「書名」,若要在圖書館中找到某本書,除非將書本編號記得很清楚否則需要透過書名去尋找。網絡上的資源也需要通過網址(URL)才能正確訪問或獲取。
在域名誕生之前,人們是通過 IP 位址來訪問資源的,IP 位址可以說是網絡世界中的地址。但 IP 位址很不好記且一旦更改就得重記,非常不方便,因而有了域名的誕生。有了域名之後,使用者可以透過輸入域名來找到資源,而不需要記憶 IP 位址。
接下來就進入正題,回答一下從使用者輸入網址,到瀏覽器呈現出來,經過了哪些過程?
1. DNS 解析
- DNS (Domain Name System) 也就是網域名稱系統,它將人們可讀取的網域名稱 (例如
www.bbc.com
) 轉換為機器可讀取的 IP 位址 (例如151.101.0.81
)。- 如果輸入的是 IP 位址,則此步驟可省略。
假設在瀏覽器輸入 https://www.bbc.com/news
之後回車,瀏覽器需要向離它最近的 DNS Server 做查詢辨識以找到域名(domain)所對應的 IP,當找到對應的 IP 時就會回傳這組 IP 的網站資料,而若沒有查詢到,則會發生像是 DNS NOT FOUND,網頁或服務無法開啓的情況。
關於DNS更詳細的內容請參考:什麼是 DNS? | DNS 的工作方式
如何找到域名所對應的 IP
在實際向 DNS 發出請求之前,瀏覽器會依序檢查以下快取,如果找不到就繼續往下找:
- 瀏覽器快取:查看瀏覽器是否已經訪問過
www.bbc.com
,如果有相應的 DNS 記錄,並且記錄尚未過期,則直接從瀏覽器的快取中取得對應的 IP 位址。 - 作業系統快取:如果瀏覽器的快取中找不到對應的記錄,瀏覽器會向作業系統發出 DNS 查詢。作業系統會檢查自身的快取,如果有相符的記錄,則會返回給瀏覽器。
- 路由器快取:如果作業系統中也沒有對應的 DNS 記錄,瀏覽器會發送 DNS 查詢請求給路由器。路由器會檢查自己的快取,如果有相應的資訊,則會回應瀏覽器。
- ISP 的 DNS 伺服器:如果前面的快取中都找不到對應的 IP 位址,瀏覽器會將查詢發送到你的網際網路服務提供商(ISP)所設定的 DNS 伺服器。這個伺服器會嘗試解析域名並找到對應的 IP 位址。
- DNS 伺服器也稱為 Name Server,它負責記錄下一層域名的資料,當有人詢問它某個域名的資料時,它要將資料傳給對方。
- 根域名伺服器解析:如果 ISP 的 DNS 伺服器也沒有相應的記錄,它會向根域名伺服器發送查詢。根域名伺服器告訴 ISP DNS 伺服器哪些頂級域名伺服器可以提供所需的資訊。
- 頂級域名伺服器解析:ISP 的 DNS 伺服器向負責
.com
頂级域的域名伺服器發出請求,該伺服器提供了管理.com
域的資訊。 - 次級域名伺服器解析:接下來,ISP 的 DNS 伺服器向負責
bbc.com
次级域的域名伺服器發出請求,獲取該域名對應的IP位址。 - 返回IP位址:最終,該次级域名伺服器將對應的IP位址返回給 ISP 的 DNS 伺服器,然後透過作業系統和路由器返回到你的瀏覽器,使你的瀏覽器可以開始與該 IP 位址的伺服器建立連接,取得網站的內容。
以上的過程又稱為 DNS lookup。
2. 建立 TCP 連線
得知伺服器 IP 後,瀏覽器會和對方建立連線以傳送資料,使用的是 TCP 協議。
TCP協議為傳輸報文提供可靠的字節流傳輸服務,它通過三次握手(three-way handshake)等手段來保證傳輸過程中的安全可靠。
三次握手過程如下:
- Client 向 Server 發送 SYN packet,並進入 SYN_SEND 狀態,等待 Server 確認。
- Server 收到 SYN packet,必須確認 client 端的 SYN (ack=j+1),同時自己也發送一個 SYN packet (syn=k),即 SYN/ACK packet,此時伺服器進入 SYN_RECV 狀態。
- Client 端從 Server 收到 SYN/ACK packet 後,向 Server 發送 ACK packet。發送完畢後,Client 端和 Server 進入 ESTABLISHED 狀態,完成三次握手。
TCP/IP 三次握手更詳細的內容可以參考4.1 TCP 三次握手与四次挥手面试题
3. 瀏覽器發起請求與接收伺服器響應
一旦建立了到 Server 的連線,瀏覽器就代表使用者發送初始的 HTTP GET 請求,對於網站來說,這個請求通常是一個 HTML 檔案。
請求中會攜帶請求頭(header),header 主要包含:
- 請求的方法 (GET, POST, PATH, PUT, DELETE…)
- 協議 (HTTP, HTTPS, FTP, SFTP…)
- 目標 URL (具體的請求路徑已知文件名)
- 一些必要信息 (快取, cookie…)
Server 收到請求並經過一些處理之後,它將返回相關的回應頭(狀態碼…等)和 HTML 檔案給瀏覽器。
HTTP 更詳細的內容請參考 An overview of HTTP
4. 瀏覽器渲染頁面
伺服器回傳的是一個 HTML 檔案,瀏覽器會解析 HTML 的內容並繪製到畫面上。
大致的流程如下:
- 解析 HTML 並構建 DOM 樹:瀏覽器解析 HTML 檔案,建立 DOM 樹(將 HTML 檔案用一個樹狀結構來描述)。
- 取得外部資源:當解析器遇到 CSS 或 JavaScript 檔案等外部資源時,它會開始取得這些檔案。解析器將在載入 CSS 檔案時繼續,儘管它會阻止渲染,直到它被載入和解析。
- 解析 CSS 並構建 CSSOM:CSSOM是所有 CSS 選擇器和每個選擇器相關屬性的映射,以樹的形式呈現,具有根節點、同級節點、後代節點、子節點等關係。
- 建立渲染樹:在前面步驟中建立的 CSSOM 和 DOM 樹組會合成一個渲染樹。
- 計算布局和繪製:現在有了完整的渲染樹,瀏覽器知道要渲染什麼,但不知道在哪裡渲染。因此,必須計算頁面的佈局(即每個節點的位置和大小)。渲染引擎遍歷渲染樹,從頂部開始向下工作,計算每個節點應顯示的座標。
解析 HTML 及構建 DOM 樹
瀏覽器最初獲得的是位元組(byte)內容的 HTML 文件,必須要轉換為人類能看得懂的內容也就是字符(HTML),雖然人類能看懂字符但機器看不懂,所以還需要將字符轉換為機器看得懂的語言符號標籤(Token)。
轉換為 Token 之後還需要將它再轉成節點(node),最後將這些節點連接在一起形成文件物件模型(DOM)。
解析 CSS 並構建 CSSOM
瀏覽器在構建 DOM 的時候就會遇到 link 標籤,然後向 Server 發送請求得到 CSS 文件,後面的流程就和處理 HTML 文件非常相似,只不過最後一步是構建成 CSSOM 而不是 DOM。
建立渲染樹
在前面步驟中建立的 CSSOM 和 DOM 樹組會合成一個渲染樹。渲染樹上的節點是頁面能夠顯示的內容,所以 <meta>
, <link>
…等標籤以及設置了 display: none
樣式的就不會被呈現出來。
計算布局和繪製
布局的意思就是獲取渲染樹的結構、節點位置和大小,而佈局是依據盒子模型來進行的,也就是每個元素都用一個盒子來表示,然後這些盒子在頁面上進行排列和嵌套。
布局完之後就會安排頁面繪製,把渲染樹以像素的形式繪製在頁面,這樣頁面就呈現出來了。
詳細的過程可以參考:
1.淺顯易懂的圖片解釋 How the browser renders a web page
2.比較詳細的過程說明 渲染页面:浏览器的工作原理
3.影片說明 浏览器渲染页面的流程