深入瞭解新式網路瀏覽器 (第 2 部分)

Mariko Kosaka

導覽過程中會發生的情況

這是部落格系列文章 (共 4 篇) 的第 2 篇,將探討 Chrome 的內部運作方式。在上一篇文章中,我們探討了不同的程序和執行緒如何處理瀏覽器的不同部分。在本篇文章中,我們將深入探討各個程序和執行緒如何溝通,以便顯示網站。

我們來看看網路瀏覽的簡單用途:您在瀏覽器中輸入網址,瀏覽器就會從網路擷取資料並顯示網頁。在本篇文章中,我們將著重於使用者要求網站,以及瀏覽器準備轉譯網頁 (又稱為導覽) 的部分。

這項作業會從瀏覽器程序開始

瀏覽器程序
圖 1:頂端為瀏覽器 UI,底端為瀏覽器程序的圖表,其中包含 UI、網路和儲存空間執行緒

第 1 部分:CPU、GPU、記憶體和多程序架構所述,分頁以外的所有內容都由瀏覽器程序處理。瀏覽器程序包含多個執行緒,例如負責繪製瀏覽器按鈕和輸入欄位的 UI 執行緒、負責處理網路堆疊以接收網際網路資料的網路執行緒,以及負責控制檔案存取權的儲存執行緒等。當您在網址列中輸入網址時,瀏覽器程序的 UI 執行緒會處理輸入內容。

簡易導覽

步驟 1:處理輸入內容

當使用者開始在網址列中輸入內容時,UI 執行緒首先會詢問「這是搜尋查詢還是網址?」。在 Chrome 中,網址列也是搜尋輸入欄位,因此 UI 執行緒需要解析並決定是否要將您導向搜尋引擎,或您要求的網站。

處理使用者輸入內容
圖 1:UI 執行緒詢問輸入內容是搜尋查詢還是網址

步驟 2:開始導航

使用者按下 Enter 鍵時,UI 執行緒會啟動網路呼叫,以便取得網站內容。載入旋轉圖示會顯示在分頁角落,網路執行緒會執行適當的通訊協定,例如 DNS 查詢和為要求建立 TLS 連線。

導航開始
圖 2:UI 執行緒與網路執行緒通訊,以便前往 mysite.com

此時,網路執行緒可能會收到 HTTP 301 等伺服器重新導向標頭。在這種情況下,網路執行緒會與 UI 執行緒通訊,指出伺服器要求重新導向。接著,系統會啟動另一個網址要求。

步驟 3:朗讀回覆

HTTP 回應
圖 3:回應標頭,其中包含 Content-Type 和酬載 (即實際資料)

回應主體 (酬載) 開始傳入後,網路執行緒會視需要查看串流的前幾個位元組。回應的 Content-Type 標頭應會指出資料類型,但由於標頭可能遺漏或錯誤,因此會執行 MIME 類型嗅探。這是「棘手的業務」,如原始碼中的註解所述。您可以參閱該註解,瞭解不同瀏覽器如何處理內容類型/酬載組合。

如果回應是 HTML 檔案,則下一步是將資料傳遞至轉譯器程序;如果是 ZIP 檔案或其他檔案,則表示這是下載要求,因此需要將資料傳遞至下載管理工具。

MIME 類型嗅探
圖 4:網路執行緒詢問回應資料是否為安全網站的 HTML

這也是SafeBrowsing 檢查的發生位置。如果網域和回應資料似乎與已知的惡意網站相符,網路執行緒就會發出警示,顯示警告頁面。此外,系統會執行Cross Origin Read Blocking (CORB) 檢查,確保敏感的跨網站資料不會傳送至轉譯器程序。

步驟 4:找出轉譯器程序

完成所有檢查後,如果 Network 執行緒確信瀏覽器應導向要求的網站,就會通知 UI 執行緒資料已就緒。接著,UI 執行緒會尋找轉譯器程序,以便繼續轉譯網頁。

尋找轉譯器程序
圖 5:網路執行緒告知 UI 執行緒尋找轉譯器程序

由於網路要求可能需要數百毫秒才能傳回回應,因此我們會套用最佳化方式來加快這個程序。當 UI 執行緒在步驟 2 中將網址要求傳送至網路執行緒時,它已知道要前往哪個網站。UI 執行緒會嘗試主動尋找或啟動與網路要求並行的轉譯器程序。如此一來,如果一切正常,網路執行緒收到資料時,轉譯器程序就會處於待命狀態。如果導覽重新導向跨網站,系統可能不會使用這個待命程序,而需要使用其他程序。

步驟 5:提交導覽

資料和轉譯器程序都已就緒,因此從瀏覽器程序傳送 IPC 至轉譯器程序,以便提交導覽。它也會傳遞資料串流,讓轉譯器程序可以持續接收 HTML 資料。一旦瀏覽器程序收到確認訊息,表示在轉譯器程序中已完成提交,瀏覽器程序就會完成導覽,並開始文件載入階段。

此時,系統會更新網址列,並在安全性指標和網站設定 UI 中顯示新網頁的網站資訊。分頁的工作階段記錄會更新,因此「前往上一個」/「前往下一個」按鈕會逐一瀏覽剛前往的網站。為了在關閉分頁或視窗時便於還原分頁/工作階段,系統會將工作階段記錄儲存在磁碟上。

提交導覽
圖 6:瀏覽器和轉譯器程序之間的 IPC,要求轉譯網頁

額外步驟:初始載入完成

導覽完成後,轉譯器程序會繼續載入資源並轉譯網頁。我們會在下一篇文章中詳細說明這個階段的情況。轉譯器程序「完成」轉譯後,就會將 IPC 傳回至瀏覽器程序 (這是在網頁中的所有影格觸發所有 onload 事件並完成執行後)。此時,UI 執行緒會停止分頁上的載入旋轉圖示。

我說「完成」是因為用戶端 JavaScript 仍可在這個時間點後載入其他資源,並轉換為新檢視畫面。

網頁載入完成
圖 7:從轉譯器傳送至瀏覽器的 IPC,用於通知網頁已「載入」

簡易導覽已完成!但如果使用者再次將不同網址放入網址列,會發生什麼情況?瀏覽器程序會透過相同的步驟前往其他網站。但在執行這項操作前,它必須先向目前顯示的網站查詢是否需要 beforeunload 事件。

beforeunload 可在您嘗試離開或關閉分頁時,建立「離開這個網站嗎?」快訊。分頁內的所有內容 (包括 JavaScript 程式碼) 都由轉譯器程序處理,因此瀏覽器程序必須在收到新的導覽要求時,向目前的轉譯器程序進行檢查。

beforeunload 事件處理常式
圖 8:瀏覽器程序傳送至轉譯器程序的 IPC,告知對方即將前往其他網站

如果導覽是由轉譯器程序啟動 (例如使用者按一下連結,或是用戶端 JavaScript 已執行 window.location = "https://newsite.com"),轉譯器程序會先檢查 beforeunload 處理常式。接著,它會經歷與瀏覽器程序相同的程序,啟動導覽。唯一的差異在於導覽要求是從轉譯器程序啟動至瀏覽器程序。

如果新導覽網頁與目前顯示的網頁不同,系統會呼叫個別的轉譯程序來處理新導覽網頁,同時保留目前的轉譯程序來處理 unload 等事件。詳情請參閱頁面生命週期狀態總覽,以及如何使用頁面生命週期 API鉤掛事件。

新的導覽和卸載
圖 9:從瀏覽器程序傳送至新轉譯器程序的 2 個 IPC,指示轉譯器程序轉譯網頁,並指示舊轉譯器程序卸載

如果是 Service Worker

這項導覽程序最近的變更之一,就是引入服務工作者。Service Worker 是一種在應用程式程式碼中編寫網路 Proxy 的方法,可讓網頁開發人員進一步控管要快取的內容,以及從網路取得新資料的時間。如果服務工作者已設為從快取載入網頁,就不需要從網路要求資料。

請務必記住,服務工作者是執行在轉譯器程序中的 JavaScript 程式碼。不過,當導覽要求傳入時,瀏覽器程序如何得知網站有服務工作者?

服務 worker 範圍查詢
圖 10:瀏覽器程序中的網路執行緒,查詢服務工作者範圍

註冊服務工作者時,服務工作者的範圍會保留做為參照 (如要進一步瞭解範圍,請參閱這篇「服務工作者生命週期」文章)。導覽發生時,網路執行緒會檢查網域是否與已註冊的服務工作者範圍相符,如果已為該網址註冊服務工作者,UI 執行緒會尋找轉譯器程序,以便執行服務工作者程式碼。服務工作站可能會從快取載入資料,因此不必從網路要求資料,也可能會從網路要求新的資源。

serviceworker 導覽
圖 11:瀏覽器程序中的 UI 執行緒啟動轉譯器程序,以便處理服務工作站;轉譯器程序中的 worker 執行緒隨後會向網路要求資料

您可以看到,如果服務工作者最終決定從網路要求資料,瀏覽器程序和轉譯器程序之間的來回通訊可能會導致延遲。Navigation Preload 是一種機制,可在服務工作者啟動時並行載入資源,加快這個程序。這項功能會為這些要求加上標頭,讓伺服器決定為這些要求傳送不同的內容,例如只傳送更新的資料,而非完整文件。

導覽預先載入
圖 12:瀏覽器處理程序中的 UI 執行緒會啟動轉譯器處理程序,以便處理服務 worker,同時啟動網路要求

總結

在本篇文章中,我們將探討導覽期間發生的情況,以及網頁應用程式程式碼 (例如回應標頭和用戶端 JavaScript) 如何與瀏覽器互動。瞭解瀏覽器從網路取得資料的步驟,有助於您瞭解為何開發導覽預先載入等 API。在下一篇文章中,我們將深入探討瀏覽器如何評估 HTML/CSS/JavaScript 以轉譯網頁。

你喜歡這篇文章嗎?如有任何問題或建議,歡迎在下方的留言區留言,或在 Twitter 上傳送訊息給 @kosamari

下一篇:轉譯器程序的內部運作方式