--- tags: System Architecture --- # 瀏覽器(Browser)原理 * [Inside look at modern web browser](https://developers.google.com/web/updates/2018/09/inside-browser-part1) * [How Browsers Work: Behind the scenes of modern web browsers](https://www.html5rocks.com/en/tutorials/internals/howbrowserswork/#The_browsers_we_will_talk_about) * [How the Puffin Browser Works](https://medium.com/coding-neutrino-blog/how-the-puffin-browser-works-440c91cece8f) ## 前導:進程(Process) & 線程(Thread): 程式常常會被劃分為幾個獨立又彼此配合的模組,瀏覽器也不利外,以Chrome為例,其是由多個進程組成,每個進程有自己核心功能,互相配合完成整體瀏覽器工作,每個進程又包含多個線程一起協同運作,以下簡單解釋進程與線程。 * 進程: 一個任務可以稱為一個程序,一個在運行中的程序就叫做進程,進程就像工廠的獨立產線,一次只能進行一個任務。程式一般是放置在實體磁碟中,然後透過使用者的執行來觸發。觸發後會載入到記憶體中成為一個個體,那就是程序,所以,**進程可以看做是作業系統進行資源分配與調度的獨立單位**。 在 Linux 系統當中:『觸發任何一個事件時,系統都會將他定義成為一個程序,並且給予這個程序一個 ID ,稱為 PID,同時依據啟發這個程序的使用者與相關屬性關係,給予這個 PID 一組有效的權限設定。』以便作業系統可管理這個程序。 在執行一個 Process 大概會有 Memory Space 和 Thread 這二個部份, Memory Space 用來進行變數的存取, Thread 就是屬於 CPU 運算的部份。Process 和 Process 之間的變數不能互相共享使用。 但一個進程可以要求系統生成另一個進程來執行不同任務,系統會為新進程分配不同內存,而兩個進程間可以使用 IPC(Inter Process Communication)進行通訊。 ![](https://i.imgur.com/p9msEbU.jpg) ![](https://i.imgur.com/6DRbmVB.png) * 線程(執行緒): 當一個程序在跑得時候,可能有好幾個程序執行流程,這些執行流就叫做線程,可以想成是產線上的多個工人,一起在執行同一個PID的任務,每個工作在動作的時候就會佔據一些資源,但資源原則上是進程所擁有,因此每個線程都會有個父進行,因此線程可以想像成輕量級的進程。 線程是獨自進行的,其不會知道有其他線程存在,對於進程的資源也是先搶先贏。 * 多線程: 一個 Process 可以啟動多個 Thread 的 CPU 資源,Thread 和 Thread 之間的變數可以互相共享使用,多執行緒使用場景: 當遇到很多的 IO 處理時:例如要把一個很大的資料寫入到資料庫或是 File System 時,如果只用一個 main 程式去做的話,就會阻礙到後面程式的執行,所以應該要另外去開一個 Thread 去做寫入資料的動作,才能增加程式的執行效率。 * Concurrent 和 Parallel 之間的差異: * Concurrent 主要是一個 CPU 交叉排程去做多件事,雖然同一個時間點一樣只會做一件事,但避免一個線程完全結束後才進行下一個線程。 * Parallel 主要是會有多個 CPU 在同一個時間點內會去做多件事,而這關係到CPU的核心數量。 ## 瀏覽器架構: 瀏覽器的製作可以是單進程多線程,或是多進程再用 IPC 進行溝通,以Chrome 為例,其是多進程架構,最頂層有一個 Browser process 協調其他進程,Chrome 主要進程如下: * Browser Process: * 地址欄、書籤、前進後退按鈕...等部分工作; * 一些瀏覽器底層操作,例如網路請求和文件訪問; * Renderer Process(渲染): * 負責一個tab內關於網頁呈現的所有工作; * Plugin Process: * 控制一個網頁用到的所有插件,如 flashGPU Process * 處理GPU相關事情 ![](https://i.imgur.com/1x9XVHz.jpg) 多進程好處是單一進程運行失敗的話,並不影響其他進程,但因為記憶體不能共用,所以進程如果要處理一樣的東西的話,其沒辦法共享。 此外,Chrome 把瀏覽器不同程序的功能看做服務,這些服務可以方便的分割為不同的進程或者合併為一個進程。 以Broswer Process 為例,如果Chrome 運行在強大的硬件上,它會分割不同的服務到不同的進程,這樣Chrome 整體的運行會更加穩定,但是如果Chrome 運行在資源貧瘠的設備上,這些服務又會合併到同一個進程中運行,這樣可以節省內存。 另外,Chrome 與許同一tab下利用獨立進程開啟 Subframe,這樣同tab下跨站資訊可以獨立渲染以增加穩定性。 ![](https://i.imgur.com/PavBWpY.jpg) ## 網頁搜尋過程 瀏覽器 Tab 外的工作主要由 Browser Process 掌控,Browser Process 又對這些工作進一步劃分,使用不同線程進行處理: * UI thread : 控制瀏覽器上的按鈕及輸入框; * network thread: 處理網絡請求,從網上獲取數據; * storage thread: 控製文件等的訪問; 步驟: 1. 處理輸入: UI thread 需要判斷用戶輸入的是 URL 還是 query; 2. 開始搜尋: network thread 會執行 DNS 查詢,隨後為請求建立 TLS 連接。 3. 讀取回應: network thread 會依據 Content-Type 及 MIME Type sniffing 判斷回應內容的格式,如果回應內容的格式是 HTML ,下一步將會把這些數據傳遞給 renderer process,如果是 zip 文件或者其它文件,會把相關數據傳輸給下載管理器。 4. 查找渲染進程: 當上述所有檢查完成,network thread 確信瀏覽器可以導航到請求網頁,network thread 會通知 UI thread 數據已經準備好,UI thread 會查找到一個 renderer process 進行網頁的渲染。 5. 確認搜尋: 進過了上述過程,數據以及渲染進程都可用了, Browser Process 會給 renderer process 發送 IPC 消息來確認導航,一旦 Browser Process 收到 renderer process 的渲染確認消息,導航過程結束,頁面加載過程開始。此時,地址欄會更新,展示出新頁面的網頁信息。 history tab 會更新,可通過返回鍵返回導航來的頁面,為了讓關閉 tab 或者窗口後便於恢復,這些信息會存放在硬盤中。 ## 渲染流程: 渲染進程幾乎負責 Tab 內的所有事情,渲染進程的核心目的在於轉換 HTML CSS JS 為用戶可交互的 web 頁面。渲染進程中主要包含以下線程: 1. 主線程 Main thread 2. 工作線程 Worker thread 3. 排版線程 Compositor thread 4. 光柵線程 Raster thread 流程: 1. 建構DOM: 當渲染進程開始接受 HTML數據時,主線程會解析本文字符串為 DOM。渲染 HTML為 DOM 的方法由 HTML Standard定義。 2. 加載次級的資源: 網頁中常常包含圖片/CSS/JS等額外資源,這些資源需要從網路或 cache 獲取,主進程在建構 DOM 時會逐一請求。 3. JS 的下載與執行: 當遇到 < script > 標籤時,渲染進程會停止解析 HTML,而去加載/解析和執行 JS 代碼,停止解析 HTML 的原因在於 JS 可能會改變 DOM 的結構。不過開發者其實也有多種方式來告知瀏覽器應對如何應對某個資源,比如說如果在< script> 標籤上添加了async 或 defer 等屬性,瀏覽器會異步的加載和執行JS 代碼,而不會阻塞渲染。 4. 樣式計算: 僅僅渲染 DOM 還不足以獲知頁面的具體樣式,主進程還會基於 CSS 選擇器解析 CSS 獲取每一個節點的最終的計算樣式值。即使不提供任何 CSS,瀏覽器對每個元素也會有一個默認的樣式。 5. 獲取布局: 想要渲染一個完整的頁面,除了獲知每個節點的具體樣式,還需要獲知每一個節點在頁面上的位置,佈局其實是找到所有元素的幾何關係的過程。其具體過程如下: 通過遍歷 DOM 及相關元素的計算樣式,主線程會構建出包含每個元素的坐標信息及盒子大小的佈局樹。佈局樹和DOM 樹類似,但是其中只包含頁面可見的元素,如果一個元素設置了display:none ,這個元素不會出現在佈局樹上,偽元素雖然在 DOM 樹上不可見,但是在佈局樹上是可見的。 6. 繪製各元素: 即使知道了不同元素的位置及樣式信息,我們還需要知道不同元素的繪製先後順序才能正確繪製出整個頁面。在繪製階段,主線程會遍歷佈局樹以創建繪製記錄。繪製記錄可以看做是記錄各元素繪製先後順序的筆記。 7. 合成幀: 現代 Chrome 其實利用了圖層概念來組合不同的層。複合是一種分割頁面為不同的層,並單獨網格化(柵格化, grid),隨後組合為幀的技術。不同層的組合由 compositor 線程(合成器線程)完成。 * Note: 網頁柵格(網格)系統 (Web Grid System) * 一種規範網頁布局呈現的方法,白話一點就是將畫面分隔一塊一塊,然後頁面內容再依需求大小放進這一格一格內 ![](https://i.imgur.com/GOnapfr.png) * [淺談CSS Grid system](https://ithelp.ithome.com.tw/articles/10139242)