學習了瀏覽器的 Process 與 Thread 之後,接著一起來看看一段網址或搜尋關鍵字被輸入網址列送出之後,在瀏覽器內部會發生什麼有趣的事情吧!

HIHI~😍 如果你是第一次來的話,『Chan-Chan-Dev』是一個專門用簡單的圖文與故事講解網路程式技術的網站。
若你也喜歡用這種方式學習的話,歡迎加入 Chan-Chan-Dev Facebook 的粉絲團,在發佈的時候就有比較多機會收到通知喔!😍

這篇的所有內容是來自於原文 《Inside look at modern web browser (part 2)》 的第二篇。其實已經講的很淺顯易懂而且又有超級可愛的插圖,私心認爲已經很難有比它寫的更好的文章了 ,因此這篇文章更像是自己學習的筆記。

另外也因爲它是英文的版本,希望藉由自己的筆記分享可以在讓更多人學習到有幫助的資訊喔!😍

前情提要

既上一篇 瀏覽器學習筆記 Part 1 - 圖解學習 Process 與 Thread! 聊過每天所使用的瀏覽器是因爲一群默默地無名的 執行緒 (Thread)行程 (Process) 相戶合作的結果。而其中扮演類似 CEO 角色負責統合調度的則是 Browswer Process

還記得上次討論 執行緒 (Thread)行程 (Process) 的關係嗎?如果忘記了也沒問題,用底下的圖片來回憶一下吧 😀
執行緒之間是彼此獨立(隔離)的

Navigation 是什麼呢?

當我們在對一個網站發起請求,而瀏覽器接收資料準備顯示這個網頁內容的過程,就叫做 Navigation 囉 😊

登場角色介紹

在本篇登場的角色,分別是都是屬於在 Browser Process 內部的 UI ThreadNetwork Thread,與 Renderer ProcessMain Thread

Browser Process

UI Thread Network Thread
瀏覽器界面上的按鈕或者是網址輸入框等等的元件都是我負責的喔! 我負責網路相關的任務以其接受由網路回傳的資料內容喔!

Renderer Process

Main Thread
Main Thread 的職責會在下一章節聊到喔 😀

由上述的分工得知,當我們不管在瀏覽器的網址列輸入什麼內容的時候,第一時間會被 UI Thread 接收處理的喔!

簡單的 Navigation 過程

處理網址輸入框輸入的內容

因爲以 Chrome 來說,網址輸入框其實扮演着兩個角色,分別是:

  • 網址列
  • 搜尋列

因此每當有內容輸入到網址輸入框時,接收到的 UI Thread 都要先判斷一下這個內容究竟是個 網址 還是需要被搜尋的關鍵字 呢?如果是搜尋關鍵字就要丟給搜尋引擎,反之如果是個網址 則需發請求到指定輸入的網址囉。

UI Thread 判斷是否爲網址內容或搜尋關鍵字

當我們按下 Enter

當輸入框輸入網址並且按下 Enter 鍵的時候,UI Thread 就會呼叫 Network Thread,請它去取得網站的內容。這時候分頁上會顯示讀取的動畫,而 Network Thread 會爲這個請求,透過適合的協定像是 DNS Lookup 並建立起 TLS 連線。

UI Thread 呼叫 Network Thread 去取得網站的內容

Redirect 301

如果在請求送出後,Network Thread 接收到對方的伺服器傳來的 redirect header 像是 301 的 HTTP 狀態回應,Network Thread 會去跟 UI Thread 說:對方伺服器請你改用另外一個網址。因此 UI Thread 會在請 Network Thread 去對新的網址發出請求囉。

讀取回應資料

我們在不同網址發起的請求都不太一樣,有的是要求一個 HTML 網頁檔案、有的是想要一個 Json 資料檔,更多時候是想要下載檔案,而檔案的種類又可以分 zip、pdf、圖檔、音樂檔等等等。對於每一個類型的檔案的處理方式都不一樣,於是對於發起的請求的瀏覽器來說,判斷回傳的資料是什麼格式就顯得極爲重要囉

回應資料所帶的不同 Content-Type

因此當請求發出之後,對方的網站伺服器有了回應傳回來時,Network Thread 首先會先看看 Content-Type 的 header 確認回傳的資料類型,至於不同的資料類型在不同的瀏覽器處理方式都有所不同,也可以參考這邊附上 Source code 的 Comment 看看 Chrome 是怎麼處理這些檔案類型的對應動作吧 😆

安全性相關的檢查

在這個階段也會針對瀏覽時的安全性(SafeBrowsing)做檢查,若是網域或者是回傳的資料與已知的惡意網站有所吻合的話,那麼 Network Thread 就會馬上跳出一個警告的頁面 💪。

針對網站安全性的檢查

此外,也會針對 跨域讀取阻擋Cross Origin Read Blocking)的檢查,確保敏感的跨域資料不會被進到 Renderer Process 😀

Renderer Process 登場

一旦上述的檢查確認完成,Network Thread 也確認收到請求的資料後,就會回報 UI Thread 這些資料已經準備好了!於是 UI Thread會找 Renderer Process 協助渲染出網頁的內容。

找個 Renderer Process

優化做法

因爲網路請求需要花一段時間才能取得回應,因此有一個加速這個流程的優化方法。

UI Thread 送出網路請求給 Network Thread 時,UI Thread 就偷跑先開始找 Renderer Process,因此這兩件事是同時進行的。當一切順利時,當回應資料回來的時候,Renderer Process 也準備好可以接手資料準備囉。

執行 Navigation

當回應的資料Renderer Process都就位時,Browser Process 就會透過 IPC 的方式通知 Renderer Process 執行 Navigation,通常會一起帶著資料流 (Data Stream),因此 Renderer Process 保持接收 HTML 資料的狀態。

Browser Process 就會透過 IPC 的方式通知 Renderer Process 執行 Navigation

一旦 Browser Process 收到 Renderer Process 開始執行的確認訊息時, Navigation 就算告一段落,也將進入開始讀取文件的階段。

在這個時間點,網址列上會更新爲安全上鎖的狀態,並且顯示新頁面的網站資訊。分頁的 Session History 也將被更新,因此才能在上一頁、下一頁按鈕被點擊的時候回到當時的頁面。此外爲了讓分頁被關閉的時候還能回復使用,Session History 是存在硬碟裡的喔。

初始化讀取完成

當 Navigation 執行完成後,Renderer Process 開始著手讀取這些資源與渲染頁面。至於這邊發生的細節則會在下一篇的時候聊到喔。

Renderer Process 完成渲染,他會送 IPC 通知給 Browser Process,這個時候 Browser Process 內的 UI Thread 就會停止在分頁上的讀取動畫。雖然說是完成渲染,但是因爲 Javascript 可能依然會讀取其他額外的資源,並且在這個時間點之後渲染新的內容喔。

UI Thread 停止在分頁上的讀取動畫

簡單的 Navigation 到這裏就完成囉!😍

離開頁面之前的確認

但是如果我們又輸入不同的網址到網址列會發生什麼事情呢? 😆
基本上還是會走上述的流程到不同的網站,只是在離開目前的網站之前,會先檢查一下目前的網站是否有使用 beforeunload 的事件。

beforeunload 可以用來製作『是否要離開網站』的提示訊息,當使用者試圖離開或關閉分頁時跳出。因爲任何在分頁內的所有東西都歸 Renderer Process 處理,因此 Browser Process 接到新的 Navigation 請求的時候,必須要確認目前的 Renderer Process 是否有針對 beforeunload 的設定囉。

Browser Process 與目前的 Renderer Process 確認是否有針對 beforeunload 的設定

另外若 Navigation 是由 Javascript 發起的,例如:

1
window.location = "https://chan-chan-dev.com"

確認是否有 beforeunload 的事件的任務就會變成 Renderer Process 的責任囉。然後走著跟 Browser Process 一樣的流程發起 Navigation。

使用新的 Renderer Process

當有新的 Navigation 到不同的網站時,會產生另一個新的 Renderer Process 來處理新的 Navigation,而目前的 Renderer Process 則繼續存在處理像是 unload 這類型的事件。

當有新的 Navigation 到不同的網站時,會產生另一個新的 Renderer Process 來處理新的 Navigation

結論 Wrap-Up

原文中有一段討論 Service Worker 的部分,自己覺得有點 Service Worker 的部分自己尚未完全理解,因此沒有加入在本篇之中,若有興趣的大大們請移駕到原文收看喔 😆

在這篇筆記中,才知道原來我們一個簡單地『把網址 Key 進去網址列輸入,並且按下 Enter 到顯示網頁內容』的背後,其實是經過 Browser Process 內部的 UI Thread 判斷輸入內容是否爲網址,若爲網址則請 Network Thread 發起請求取回資料,在中間 Network Thread 又會做不同的檢查到判斷回應的內容類型等等,等到資料回來了才能發起一個 Renderer Process(也可以如同上面所提到的優化方式同時進行),進而請 Renderer Process 渲染出 HTML 的內容。中間還有包含其他手續例如:更新分頁上的讀取動畫等等。

看似簡單的小功能,居然需要這麼多環節的任務串接起來,才能達到我們平常以爲『瀏覽器就該這樣執行的功能』,也令我著實大開眼界 😮

在下一篇當中也要跟大家聊聊第三篇 《Inside look at modern web browser - Part3》。剛剛上述都用『請 Renderer Process 協助渲染 HTML 頁面內容』這句話簡單地帶過,但是實際上在 Renderer Process 會是怎麼運作的呢?有興趣的大大們可以搶先收看原文喔!😀


最後感謝你願意看到這裏,希望這篇文章對你有所幫助。

若你想到身邊有需要這篇文章內容的朋友,也請你幫他一個忙把這篇文章分享給他 😍

若文章的內容有錯誤的地方,也歡迎隨時一起討論交流。😘

最後感謝你的閱讀囉,我們下次見!Bye ~ 🚀

參考