重學瀏覽器(2)-程式間的互動

學習會讓你青春永駐發表於2019-07-11

本篇文章我們去探討下Chrome的內部工作機制,分析下不同的程式和執行緒是如何處理瀏覽器的各部分功能。同時深入研究下每個程式和執行緒在展現網站時是如何溝通的。

首先我們先來看一個簡單的例子,在瀏覽器位址列輸入url,按下回車建,瀏覽器會向伺服器請求資料然後展現介面。

從瀏覽器程式開始
從第一篇文章中,我們知道了在tab網頁之外的所有功能,都是由瀏覽器程式控制的,瀏覽器程式中有繪製瀏覽器的按鈕和輸入框的UI執行緒,網路執行緒來處理網路堆疊從網路中獲取資料,儲存執行緒控制檔案的許可權等。當輸入url按下enter鍵後,UI執行緒會處理我們的輸入。

重學瀏覽器(2)-程式間的互動

處理位址列中的輸入
使用者在位址列輸入之後,UI執行緒回去判斷使用者的輸入是url還是一個搜尋項,因為chrome的位址列也可以作為一個搜尋輸入框來使用。所以UI執行緒需要判斷使用者的的輸入然後決定把使用者的輸入傳送給搜尋引擎還是發起網路請求。

重學瀏覽器(2)-程式間的互動

開始導航
當使用者敲擊enter鍵, UI執行緒為了得到網頁內容初始化一個網路請求,即UI執行緒通知網路執行緒去載入某個網頁,這時候瀏覽器位址列左邊的載入圖示會顯示出來,同時網路執行緒會去建立網路連結,這個過程中有著例如DNS解析或者TLS連結建立等過程。

在這個節點,服務端有可能給網路執行緒返回一個重定向的狀態例如HTTP301,這時網路執行緒會告訴UI執行緒說:“你的請求被重定向了”,然後UI執行緒就會初始化另外一個網路請求。

讀取響應資料
如果服務端返回的是資料是HTML,網路執行緒會把資料直接傳送給渲染程式(瀏覽器核心),但是如果是zip檔案或者是其他型別的檔案,這代表著這是一次下載請求,網路執行緒會把資料傳送給下載管理器。

重學瀏覽器(2)-程式間的互動

同時這個過程也會發生瀏覽器的安全檢查,如果響應域和返回資料與已知的惡意站點所匹配,網路執行緒會告訴渲染程式展示一個警告介面,同時為了確保不會把危險的跨域資料傳送給渲染程式也會進行CORB檢測。

找尋渲染程式
當所有的檢查都完成後,網路執行緒確定瀏覽器應該導航到對應的請求站點,網路執行緒告訴UI執行緒資料已經準備完畢,然後UI執行緒找到渲染程式繼續去渲染介面。

由於網路請求需要幾百毫秒才能得到響應返回,瀏覽器應用了一種用來加速這個過程的優化策略,當UI執行緒傳送一個網路請求給網路執行緒的同時, UI執行緒會主動嘗試去查詢或啟動一個渲染程式,這個過程是並行執行的。使用這種方法,如果一切進展順利的話,當網路執行緒接收到資料時,渲染程式已經處於待機狀態了,當然如果請求被重定向的話則不會用到這個準備好的渲染程式。

提交導航
當返回資料和渲染程式準備好時,瀏覽器程式會通過IPC通道向渲染程式提交導航,同時傳遞資料流給渲染程式,一旦瀏覽器程式確認提交導航已在渲染器程式中發生,導航過程就完成了,文件載入階段就開始了。
此時,位址列的狀態已經更新,同時tab欄的路由歷史記錄也被更新,點選前進和後退按鈕會進行響應的介面跳轉。為了方便在tab頁或瀏覽器視窗關閉後還原瀏覽器介面,tab頁的導航歷史記錄資訊是儲存在硬碟上的。

初始載入完成
導航欄的工作完成後,渲染程式會繼續載入資源渲染介面,當渲染程式完成介面渲染後,它會通過IPC通道向瀏覽器程式(這是當頁面中包括frame中的onload事件觸發後才執行的)。在這時,瀏覽器程式中的UI執行緒會停止loading圖示的顯示。

重學瀏覽器(2)-程式間的互動

跳轉至另一個頁面
簡單的導航完成了! 但是如果使用者再次將不同的URL放到位址列會發生什麼? 好吧,瀏覽器程式會執行相同的步驟來導航到不同的站點。 但在它可以做之前,如果他們關心beforeunload事件,它需要檢查當前渲染的站點。

當你準備離開或者關閉當前介面時,beforeunload事件會觸發一個 “是否離開當前介面?”的彈框,當然,彈框的是有由渲染程式控制的,瀏覽器程式會向渲染程式詢問是否需要觸發beforeunload事件。​
重學瀏覽器(2)-程式間的互動

如果跳轉是由渲染程式中發起的,例如使用者點選了link跳轉按鈕或者在js中執行window.location=“https://newsite.com”,渲染程式會首先去檢測beforeunload處理事件,然後,它經歷與瀏覽器程式啟動導航的相同過程。 唯一的區別是導航請求從渲染程式啟動然後到瀏覽器程式。

當導航到一個與當前介面不同的新站點時,一個新的渲染程式會被建立用來處理新的導航,老的渲染程式會去處理類似於unload這種事件。對於介面的生命週期,我們可以檢視這篇文章。https://developers.google.com/web/updates/2018/07/page-lifecycle-api#overview_of_page_lifecycle_states_and_events

重學瀏覽器(2)-程式間的互動

service woker帶來的不同
由於瀏覽器新引入的service worker特性,介面的導航過程發生了一些變化。service worker是在應用程式碼中編寫網路代理的方式,允許web開發者更好的控制本地快取內容,同時也可以控制介面什麼時候向服務請求資料。當service worker 代理資源請求從快取中獲取,就不會向伺服器傳送請求。

其中最重要的一點是servicer worker是一段執行在渲染程式中的js 程式碼,所以問題就是,當一個網路請求打進來,瀏覽器程式是怎麼知道這個站點存在service worker 執行緒呢?

當一個service worker被註冊時,將保留service worker的scope作為參考 ,當請求發生時,網路執行緒根據註冊的service worker 的scope 檢查該URL,如果為該URL註冊了service worker,則UI執行緒找到渲染程式以執行service worker程式碼。service worker可以從快取載入資料,無需從網路請求資料,當然不符合規則時也可以從網路請求新資源。

重學瀏覽器(2)-程式間的互動

總結
在這篇文章中,我們研究了介面請求過程中發生的情況以及響應頭和客戶端JavaScript等Web應用程式程式碼如何與瀏覽器互動。 瞭解了瀏覽器通過網路獲取資料的步驟,可以更容易地理解為什麼使用請求預載入等API。 在下一篇文章中,我們將深入探討瀏覽器如何評估HTML / CSS / JavaScript以呈現頁面。

相關文章