(詳解)從瀏覽器輸入 URL 到頁面展示過程

引言

對於面試常問的從瀏覽器輸入 URL 到頁面展示過程發生了什麼?,我想大家都或多或少能說出一二。但是,其實這個問題很有深度,而你是否回答的有深度,在很大程度上會影響到面試官對你的印象。

並且,網上各種資料都是淺嘗輒止地講解這個過程,經常會出現今天看到這個版本,明天看到另一個版本地情況。所以,這次我們就來深入淺出一下這整個過程~

一、Chrome 多進程架構

首先,在開始講解整個過程前,我們需要認識一下 Chrome 多進程架構。因爲,從瀏覽器輸入 URL 到頁面渲染的整個過程都是由 Chrome 架構中的各個進程之間的配合完成。

Chrome 的多進程架構:

  • 瀏覽器進程,它負責用戶界面(地址欄、菜單等等)、子進程的管理(例如,進程間通信和數據傳遞)、存儲等等
  • 渲染進程,它負責將接收到的 HTML 文檔和 JavaScript 等轉化爲用戶界面
  • 網絡進程,它負責網絡資源的請求,例如 HTTP請求、WebSocket 模塊
  • GPU(圖形處理器)進程,它負責對 UI 界面的展示
  • 插件進程,它負責對插件的管理

二、過程詳解

2.1 解析輸入

發生這個過程的前提,用戶在地址欄中輸入了 URL,而地址欄會根據用戶輸入,做出如下判斷:

  • 輸入的是非 URL 結構的字符串,則會用瀏覽器默認的搜索引擎搜索該字符串
  • 輸入的是 URL 結構字符串,則會構建完整的 URL 結構,瀏覽器進程會將完整的 URL 通過進程間通信,即 IPC,發送給網絡進程

2.2 請求過程

在網絡進程接收到 URL 後,並不是馬上對指定 URL 進行請求。首先,我們需要進行 DNS 解析域名得到對應的 IP,然後通過 ARP 解析 IP 得到對應的 MACMedia Access Control Address)地址。

域名是我們取代記憶複雜的 IP 的一種解決方案,而 IP 地址纔是目標在網絡中所被分配的節點。MAC 地址是對應目標網卡所在的固定地址。

1. DNS 解析

DNS 解析域名的過程分爲以下幾個步驟:

  • 詢問瀏覽器 DNS 緩存
  • 詢問本地操作系統 DNS 緩存(即查找本地 host 文件)
  • 詢問 ISPInternet Service Provider)互聯網服務提供商(例如電信、移動)的 DNS 服務器
  • 詢問根服務器,這個過程可以進行遞歸和迭代兩種查找的方式,兩者都是先詢問頂級域名服務器查找

2. 通信過程

首先,建立 TCP 連接,即三次握手過程

  • 客戶端發送標有 SYN 的數據包,表示我將要發送請求。
  • 服務端發送標有 SYN/ACK 的數據包,表示我已經收到通知,告知客戶端發送請求。
  • 客戶端發送標有 ACK 的數據包,表示我要開始發送請求,準備被接受。

然後,利用 TCP 通道進行數據傳輸

  • 服務端接收到數據包,併發送確認數據包已收到的消息到客戶端,不斷重複這個過程
  • 客戶端在發送一個數據包後,未接收到服務端的確定消息,則重新發送該數據包,即 TCP 的重發機制
  • 當接收完所有的數據包後,接收端會按照 TCP 頭中的需要進行排序,形成完整的數據

最後,斷開 TCP 連接,即四次握手過程

  • 客戶端發送請求,申請斷開連接,進入等待階段,此時不會發送數據,但是會繼續接收數據。
  • 服務端接收請求後,告知客戶端已明白,此時服務端進入等待狀態,不會再接收數據,但是會繼續發送數據。
  • 客戶端收到後,進入下一階段等待。
  • 服務端發送完剩餘的數據後,告知客戶端可以斷開連接,此時服務端不會發送和接收數據。
  • 客戶端收到後,告知服務端我開始斷開連接。
  • 服務端收到後,開始斷開連接。

而這整個過程的客戶端則是網絡進程。並且,在數據傳輸的過程還可能會發生的重定向的情況,即當網絡進程接收到狀態碼爲 3xx 的響應報文,則會根據響應報文首部字段中的 Location 字段的值進行重新向,即會重新發起請求

3. 數據處理

當網絡進程接收到的響應報文狀態碼,進行相應的操作。例如狀態碼爲 200 OK 時,會解析響應報文中的 Content-Type 首部字段,例如我們這個過程 Content-Type 會出現 application/javascripttext/csstext/html,即對應 Javascript 文件、CSS 文件、HTML 文件。

詳細的 MIME 類型講解可以看 MDN

2.3 創建渲染進程

當前需要渲染 HTML 時,則需要創建渲染進程,用於後期渲染 HTML。而對於渲染進程,如果是同一站點是可以共享一個渲染進程,例如 a.abc.comc.abc.com 可以共享一個渲染渲染進程。否則,需要重新創建渲染進程

需要注意的是,同站指的是頂級域名二級域名相等

2.4 開始渲染

在創建完渲染進程後,網絡進程會將接收到的 HTML、JavaScript 等數據傳遞給渲染進程。而在渲染進程接收完數據後,此時用戶界面上會發生這幾件事:

  • 更新地址欄的安全狀態
  • 更新地址欄的 URL
  • 前進後退此時 enable,顯示正在加載狀態
  • 更新網頁

2.5 渲染過程

大家都知道頁面渲染的過程也是面試中單獨會考的點,並且時常會由這個點延申出另一個問題,即如何避免迴流和重繪。

渲染過程,是整個從理器輸入 URL 到頁面渲染過程的最後一步。而頁面渲染的過程可以分爲 9 個步驟:

  • 解析 HTML 生成 DOM
  • 解析 CSS 生成 CSSOM
  • 加載或執行 JavaScript
  • 生成渲染樹(Render Tree
  • 佈局
  • 分層
  • 生成繪製列表
  • 光柵化
  • 顯示

2.5.1 構建 DOM 樹

由於網絡進程傳輸給渲染進程的是 HTML 字符串,所以,渲染進程需要將 HTML 字符串轉化成 DOM 樹。例如:

需要注意的是這個 DOM 樹不同於 Chrome-devtoolElement 選項卡的 DOM 樹,它是存在內存中的,用於提供 JavaScriptDOM 的操作。

2.5.2 構建 CSSOM

構建 CSSOM 的過程,即通過解析 CSS 文件、style 標籤、行內 style 等,生成 CSSOM。而這個過程會做這幾件事:

  • 規範 CSS,即將 color: blue 轉化成 color: rgb() 形式,可以理解成類似 ES6ES5 的過程
  • 計算元素樣式,例如 CSS 樣式會繼承父級的樣式,如 font-sizecolor 之類的。

CSS Object Model 是一組允許用 JavaScript 操縱 CSSAPI。詳細 API 講解可以看 MDN

2.5.3 加載 JavaScript

通常情況下,在構建 DOM 樹或 CSSOM 的同時,如果也要加載 JavaScript,則會造成前者的構建的暫停。當然,我們可以通過 defersync 來實現異步加載 JavaScript。雖然 defersync 都可以實現異步加載 JavaScript,但是前者是在加載後,等待 CSSOMDOM 樹構建完後才執行 JavaScript,而後者是在異步加載完馬上執行,即使用 sync 的方式仍然會造成阻塞。

JavaScript 執行的過程,即編譯和運行 JavaScript 的過程。由於 JavaScript解釋型的語言。所以這個過程會是這樣的:

  • 針對每句代碼進行分行處理,即 Token
  • 根據 Token,生成 ASTAbstract Sytanx Tree) 抽象語法樹和創建上下文
  • 解釋器解析和執行 AST,生成字節碼。
  • 編譯器針對需要反覆執行的代碼,生成對應的機器碼,提高運行效率

2.5.4 生成渲染樹(Render Tree)

在有了 DOM 樹和 CSSOM 之後,需要將兩者結合生成渲染樹 Render Tree,並且這個過程會去除掉那些 display: node 的節點。此時,渲染樹就具備元素和元素的樣式信息。

2.5.5 佈局

根據 Render Tree 渲染樹,對樹中每個節點進行計算,確定每個節點在頁面中的寬度、高度和位置。

需要注意的是,第一次確定節點的大小和位置的過程稱爲佈局,而第二次才被稱爲迴流

2.5.6 分層

由於層疊上下文的存在,渲染引擎會爲具備層疊上下文的元素創建對應的圖層,而諸多圖層的疊加就形成了我們看到的一些頁面效果。例如,一些 3D 的效果、動畫就是基於圖層而形成的。

值得一提的是,對於內容溢出存在滾輪的情況也會進行分層

2.5.7 生成繪製列表

對於存在圖層的頁面部分,需要進行有序的繪製,而對於這個過程,渲染引擎會將一個個圖層的繪製拆分成繪製指令,並按照圖層繪製順序形成一個繪製列表。

2.5.8 光柵化

有了繪製列表後,渲染引擎中的合成線程會根據當前視口的大小將圖層進行分塊處理,然後合成線程會對視口附近的圖塊生成位圖,即光柵化。而渲染進程也維護了一個柵格化的線程池,專門用於將圖塊轉爲位圖。

柵格化的過程通常會使用 GPU 加速,例如使用 wil-changeopacity,就會通過 GPU 加速顯示

2.5.9 顯示

當所有的圖塊都經過柵格化處理後,渲染引擎中的合成線程會生成繪製圖塊的指令,提交給瀏覽器進程。然後瀏覽器進程將頁面繪製到內存中。最後將內存繪製結果顯示在用戶界面上。

而這個整個從生成繪製列表、光柵化、顯示的過程,就是我們常說的重繪的過程

結語

整個瀏覽器輸入 URL 到頁面渲染的過程涉及到的知識點非常廣,如 Chrome 多進程的架構、HTTP 通信過程、瀏覽器解析 JavaScript 過程、瀏覽器繪製頁面過程以及一些計算機的基礎知識等等,並且,這整個過程的分析其實和 Chrome-devtools 密切相關,所以很好的使用 Chrome-devtools 是非常重要的,後續應該會出一篇關於使用 Chrome-devtools 的指南。當然,本篇文章仍然存在諸多不足,歡迎提 issue ~

寫作不易,如果你覺得有收穫的話,可以帥氣三連擊!!!

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章