[譯] Google 圖解:輸入 URL 按下 “Enter”,Chrome 幹了什麼?

文 | Mariko Kosaka
譯 | 承香墨影
Chrome 算是程式員的標配了,從全球的市場份額來看,它在全球市場的份額已經超過 60%。
在 Chrome 10 週年之際,官方釋出了一個系列文章,用圖解的方式,很清晰的講解了現代瀏覽器的執行原理。
本文是該系列的第二篇,為了便於閱讀,我做了簡單修改和註釋,建議順序閱讀:
-
ofollow,noindex" target="_blank">現代瀏覽器多程序架構(Chrome 舉例) 。
老規矩,覺得本文有幫助,就點贊、留言或者轉發分享吧。你喜歡總要讓我知道吧!
導航的背後,發生了什麼?
這是關於 Chrome 內部原理系列文章中的第 2 篇。在上一篇文章中,我們研究了不同的 程序和執行緒中,如何處理瀏覽器的不同功能 。在這篇文章中,我們深入研究了每個程序和執行緒如何進行通訊以及最終顯示網站。
讓我們看一個最常見的操作:你在瀏覽器中輸入 URL,然後瀏覽器從網路獲取資料,並顯示頁面。在這篇文章中,我們將重點講解使用者請求網站,以及瀏覽器如何呈現網頁的部分,這個操作也被稱為 導航 。
從瀏覽器程序開始
正如我們在第 1 部分中所述: CPU,GPU,記憶體和多程序架構 ,選項卡外部的所有內容,都由瀏覽器程序來處理。
瀏覽器程序具有諸如用來繪製瀏覽器按鈕和輸入文字的 UI 執行緒;處理網路堆疊以及從網際網路接受資料的網路執行緒;控制對檔案訪問的儲存執行緒等等。例如,當你在位址列中輸入 URL 時,輸入的這個動作,將有瀏覽器程序的 UI 執行緒處理

一次簡單的導航
1. 處理輸入
當用戶開始輸入位址列時,UI 執行緒首先會去判斷 “這是搜尋查詢還是 URL?” 。
在 Chrome 中,位址列同時具備搜尋查詢的功能,因此 UI 執行緒需要解析並確定是將請求傳送到搜尋引擎,還是傳送到待請求的網站。

2. 開始導航
當用戶點選 “Enter” 時,UI 執行緒啟動網路請求,以獲取站點內容。載入中狀態顯示在選項卡的左邊,並且網路執行緒通過適當的協議,如 DNS 查詢和 TLS 為請求建立連線。

此時,網路執行緒可以接收並處理 HTTP 301 這樣的伺服器重定向,在這種情況下,網路執行緒與處理伺服器重定向請求的 UI 執行緒通訊,之後將啟動另一個 URL 請求。
3. 讀取 Response
一旦響應體(payload)開始接收,網路執行緒會在必要時,檢視資料流的前幾個位元組,獲取響應報文頭。
報文頭的 Content-Type
用來說明它是什麼型別的資料,但由於它可能丟失或錯誤,所以在這裡還需要通過 MIME 型別嗅探,來進一步判斷資料型別。這其實是一個很複雜的邏輯,你可以通過閱讀原始碼,以瞭解不同的瀏覽器如何處理 Content-Type/Payload。

如果判斷是 HTML 檔案,那麼下一步就是將資料,傳遞給渲染器程序,但如果它是 zip 檔案或其他檔案,則表示這是下載請求,因此需要將資料傳遞給下載管理器。

網路執行緒會檢查響應資料是否是來自 Safe Browsing(安全站點)的 HTML。如果域或響應資料與已知的惡意網站相匹配,則網路執行緒會發出警告,並顯示警告頁面。此外,還可能會觸發 CORB(Cross Origin Read block)檢查,用來確保敏感的跨站點資料無法進入渲染器程序。
需要注意,CORB 發生在 subDownloads 階段,但是不會發生在頂級導航中。在頂級導航中,會建立一個安全上下文,而瀏覽器會決定那個渲染器應該處理它,因此,在這種情況下,CORB 是不會執行的。
4. 查詢渲染器程序
完成所有的檢查,並且當網路執行緒確定瀏覽器會導航到請求的站點時,網路執行緒將通知 UI 執行緒,資料已經準備就緒。然後,UI 執行緒通知渲染器程序,進行網頁的渲染。

網路請求是一個耗時操作,這中間可能需要幾百毫秒的才能得到響應,因此會對此過程進行加速優化。
當 UI 執行緒在步驟 2 時,向網路執行緒傳送 URL 請求,瀏覽器已經能確定他們正在導航的站點。UI 執行緒嘗試與網路請求並行執行,主動查詢複用或啟動渲染器程序。這樣如果一切順利,則當網路執行緒開始接收資料時,渲染器程序已處於待用狀態。如果導航重定向的 URL 跨站點了,則可能不會使用此備用程序,在這種情況下就需要其他程序來處理了。
5. 提交導航
現在資料和渲染器程序已經準備就緒,為了提交導航,IPC 將從瀏覽器程序傳送一個數據流到渲染器程序。因為此處傳遞的是一個數據流,渲染器程序可以繼續從資料流中接收 HTML 資料。一旦瀏覽器程序監聽到渲染器程序中已經確認提交,一次導航就算完成了,接下來就是文件載入階段。
此時,位址列會更新,安全鎖(HTTPS證書安全)和站點設定 UI 會顯示新頁面的站點資訊。選項卡的歷史記錄將更新,因此後退/前進按鈕將允許操作之前的瀏覽器歷史。同時會將歷史記錄儲存在磁碟上,以確保關閉選項卡或視窗後,依然可以瀏覽歷史以及還原視窗。

額外步驟:初始載入完成
提交導航後,渲染器程序繼續載入資源,並顯示頁面。我們將在下一篇文章中詳細介紹該階段的情況。
一旦渲染器程序 “完成” 渲染,它就會通過 IPC 將訊息通知回瀏覽器程序(這是在所有頁面中的 onload
事件都觸發之後執行的)。此時,UI 執行緒會隱藏選項卡上的載入進度圖示。
這裡的 “完成” 之所以加引號,因為客戶端 JavaScript 仍然可以載入額外的資源,並在此之後呈現新的檢視。

導航到其他站點
簡單的導航,到這裡就算完成了。但是如果使用者再次將不同的 URL 放到位址列會發生什麼?
瀏覽器程序會通過相同的步驟,導航到不同的站點。但在此之前,它需要檢查當前顯示的網站是否註冊了 beforeunload
事件。
當你嘗試新導航或關閉選項卡時, beforeunload
可以觸發顯示 “離開這個網站嗎?” 這個彈窗,用以提示使用者。選項卡內的所有內容,包括 JavaScript 程式碼都是由渲染器程序處理,因此瀏覽器程序必須在新導航請求發起時,檢查當前的渲染器程序。
注意:不要無條件的新增 beforeunload
,它會產生更多的延遲,應該僅在需要時才監聽此事件。例如,警告使用者,他們可能會丟失在頁面上輸入的資料。

如果導航是從渲染器程序發起的,例如使用者點選超連結或 JavaScript 程式碼執行 window.location="https://newsite.com"
,則渲染器程序首先檢查 beforeunload
。然後,它將執行瀏覽器程序啟動導航相同的過程,唯一的區別,是導航請求是從渲染器程序啟動到瀏覽器程序。
當新導航進行到與當前渲染的網站不同的網站時,會呼叫單獨的渲染程序來處理新導航,同時保持當前渲染程序用於處理類似 unload
事件。更多資訊,可以參閱頁面生命週期概覽以及如何使用 Page Lifecycle API 。

在上圖中,瀏覽器程序到渲染器程序,有兩次 IPC,用來通知渲染新頁面並通知舊渲染器程序 Unload。
Service Worker 的情況下
最近在導航過程中,引入了 Service Worker(服務工作執行緒) 。Service Worker 是瀏覽器獨立於網頁執行的服務指令碼,它允許 Web 開發人員,更好地控制本地快取內容,以及必要時從網路獲取新資料。如果將 Service Worker 設定為從快取載入頁面,則無需從網路請求資料。

需要注意,Service Worker 是在渲染器程序中執行 JavaScript 程式碼,但是當導航請求發起時,瀏覽器程序如何知道該站點有 Service Worker 呢?
註冊 Service Worker 時,將保留 Service Worker 的範圍引用。當導航發生時,網路執行緒根據註冊的 Service Worker 範圍檢查域,如果為該 URL 註冊過 Service Worker,則 UI 執行緒找到渲染器程序,並執行 Service Worker 的邏輯程式碼。 Service Worker 可以直接從快取中載入資料,而無需通過網路獲取資料,如果在快取中沒有查到資料,再通過網路請求獲取資料。

如上圖,瀏覽器程序中的 UI 執行緒,啟動渲染器程序來處理 Service Worker,除此之外,還有可能工作執行緒會從網路請求資料。
導航預載入
可以預想到,如果 Service Worker 最終需要從網路獲取資料,則瀏覽器程序和渲染器程序之間的通訊,可能會導致延遲。 導航預載入 是一種通過與 Service Worker 並行載入資源,來加速此過程的機制。它用 Header 標記這些請求,允許伺服器決定為這些請求傳送不同的內容。例如,只更新部分資料而不是完整檔案。

小結
在本篇文章中,我們研究了在導航的過程中,執行的流程以及響應頭和客戶端 JavaScript 等 Web 應用程式的程式碼,如何與瀏覽器進行互動。瞭解了瀏覽器通過網路獲取資料的步驟,可以更容易地理解為什麼開發導航預載入等 API。
在下一篇文章中,我們將深入探討瀏覽器如何處理 HTML/CSS/JavaScript 並呈現在頁面上。
如果本文有幫助,留言、點贊和轉發,是最大的支援,謝謝!
原文地址:
https://developers.google.com/web/updates/2018/09/inside-browser-part2
參考閱讀:
MIME Type:https://developer.mozilla.org/en-US/docs/Web/HTTP/Basics_of_HTTP/MIME_types
SafeBorwsing:https://safebrowsing.google.com/
CORB:https://www.chromium.org/Home/chromium-security/corb-for-developers
頁面生命週期:https://developers.google.com/web/updates/2018/07/page-lifecycle-api#overview_of_page_lifecycle_states_and_events
Page Lifecycle API:https://developers.google.com/web/updates/2018/07/page-lifecycle-api
Service Worker:https://developers.google.com/web/fundamentals/primers/service-workers/
「 聯機圓桌 」:point_left:推薦我的知識星球,一年 50 個優質問題,上桌聯機學習。
公眾號後臺回覆成長『 成長 』,將會得到我準備的學習資料,也能回覆『 加群 』,一起學習進步;你還能回覆『 提問 』,向我發起提問。
推薦閱讀:
圖解 Chrome,架構篇 | 利用預處理指令碼,管理小程式程式碼 | 分詞,科普及解決方案 | 圖解:HTTP 範圍請求 | 小程式學習資料 | HTTP 內容編碼 | 輔助模式實戰 | 輔助模式玩出花樣 | 小程式 Flex 佈局

聽說喜歡 留言和分享 的人,會有好運來哦