【多學多看】現代瀏覽器如何工做

本系列分4個部分來說述Chrome瀏覽器是如何工做的。
若是你想知道瀏覽器如何將你寫好的代碼(HTML/CSS/JAVASCRIPT)變成你所看到的網頁這一過程所發生的細節,那麼本文章適合你。面試

目錄以下

  1. Chrome瀏覽器的架構
    • 介紹計算機的核心術語以及Chrome瀏覽器的架構--->【多進程多線程架構】
  2. 瀏覽器如何展現一個頁面
    從瀏覽器的【導航欄(UI Thread)】出發,深挖在【多進程多線程】的架構下  
        各個進程 :: Process   
            各個線程 :: Thread  
                之間如何【通訊】  
        ------⏬------  
        來最終展現網頁
    複製代碼
  3. 瀏覽器內核是如何工做的
    • Chrome瀏覽器內核---> 渲染進程(Renderer)是如何工做的
  4. 瀏覽器如何與用戶交互
    • 瀏覽器如何處理與用戶的交互,並反饋至網頁

1. Chrome瀏覽器的架構

準備工做

瀏覽器是一個應用程序(Application),在一個計算機上運行一個應用程序,都須要哪些東西呢?
最基本的3點(把大象裝冰箱):chrome

  1. 硬件(Machine Hardware)
  2. 操做系統(Operating System)
  3. 應用程序(Application)
    alt
    tips: 計算機體系結構的三層。機器硬件在底部,操做系統在中間,應用程序在頂部

瀏覽器的工做離不開硬件和操做系統的支持,關於這塊,咱們須要知道的知識有:跨域

  1. CPU (中央處理器)
  2. GPU (圖形處理單元)
  3. Process (進程)
  4. Thread (線程)

這裏能夠作一個簡單的解釋(看圖說話)
具體細節能夠自行去了解,特別是進程與線程的概念。瀏覽器

  • CPU && GPU
    alt
  • Process && Thread
    alt

正式開始

知道了進程和線程的概念。
那麼如何使用進程和線程構建Web瀏覽器呢?
其實答案並非惟一的安全

  • 可使用一個進程包含許多線程(圖左👈)
  • 多個進程,每一個進程包含一些線程,進程之間相互通訊(圖右👉)
    alt

這裏咱們研究的是最近的架構,即多進程多線程架構。
bash

alt
如圖所示。
瀏覽器的主要進程有:

  • Browser Process
    • 控制應用程序的chrome部分,包括地址欄、書籤、後退和前進按鈕(UI thread)
    • 處理Web瀏覽器一些UI上未顯示的功能,例如網絡請求和文件訪問等(network thread)
  • Renderer Process
    • 控制顯示網站的標籤內的全部內容
  • Plugin Process
    • 網站使用的全部插件
  • GPU Process
    • 與其餘進程隔離地處理GPU任務。GPUs處理來自多個不一樣應用程序的請求並把它們畫在屏幕上

其中最頂部是【Browser Process】,其負責協調應用程序的其餘進程。
對於渲染進程【Renderer Process】,每個Tab欄均可理解爲建立了一個渲染進程。網絡

alt

整個瀏覽器還有其餘的進程,例如Extension process 和 utility process。
具體查看瀏覽器運行的時候都開啓了哪些進程,能夠點擊右上角的:按鈕,選擇【更多工具】,點擊【任務管理器】。這裏能夠看到瀏覽器開啓的全部進程。多線程

瀏覽器多進程多架構的好處

有哪些好處其實隨便想一想就有不少(暫不詳述)。架構

  1. 單個頁面崩潰不會影響其餘頁面
  2. 安全性
  3. 健壯性

節約內存

Chrome正在進行架構更改,以將瀏覽器程序的每一個部分做爲一項服務運行,從而能夠輕鬆拆分爲不一樣的進程或整合爲一個進程。
工具

alt

站點隔離

網站隔離是Chrome最近引入的功能,可爲每一個跨網站iframe運行單獨的渲染器進程。 自Chrome 67起,默認狀況下在桌面上啓用了網站隔離功能,標籤中的每一個跨網站iframe都會得到一個單獨的渲染器進程(可經過chrome內部的【任務管理器】查看)

alt

小結

本節只須要理解:

  1. Chrome瀏覽器是多進程多線程架構的
  2. Chrome瀏覽器的主要進程有
    • Browser Process(負責統籌全局)
    • GPU Process(負責圖像處理)
    • Plugin Process(負責運行插件)
    • Renderer Process(負責渲染頁面)
  3. Chrome瀏覽器多進程多架構的好處
    • 頁面渲染互不影響
    • 安全性,沙箱
    • 健壯性
  4. 站點隔離
    • 每一個頁面中引入iframe都會開啓一個進程

2. 瀏覽器如何展現一個頁面

有一道很常見的面試題: 【從地址欄輸入url都發生了什麼】
咱們就從瀏覽器的導航開始,從瀏覽器的地址欄輸入url,都發生了什麼:

從 Browser process開始

  • 當地址欄中輸入URL時,輸入將由瀏覽器進程的UI線程處理

Step1: 處理輸入

  • 瀏覽器會判斷你在地址欄的輸入是一個搜索查詢仍是一個URL,以便決定是將你的輸入放入搜索引擎去查詢,仍是幫你發送一個網頁請求。
    alt

2.Step2:開始導航

  • 鍵盤敲入enter,UI線程啓動網絡調用以獲取網站內容。Tab項的左端Loading的那個小logo就會開始轉圈,而且network線程會經過適當的協議(UDP)進行DNS查詢而且創建TLS鏈接。
  • 此時若是network請求收到來自服務端的響應例如HTTP重定向301,那麼就會跟UI Thread通訊,告訴UI Thread服務端redirect了,那麼另外一個URL請求將會被啓動。重複進行這一步驟。

3.Step3:處理響應

  • 一旦響應主體(有效負載)開始出現,網絡線程將在必要時查看流的前幾個字節,響應的Content-Type標頭應說明數據的類型,但因爲可能丟失或錯誤,所以在此處進行MIME類型嗅探。
  • 若是響應是HTML文件,則下一步是將數據傳遞到渲染器進程,可是若是是zip文件或其餘文件,則意味着這是下載請求,所以他們須要將數據傳遞到下載管理器
    alt
  • network線程從安全站點詢問響應數據是否爲HTML
  • 這也是進行安全瀏覽檢查的地方
  • 若是域和響應數據與已知的惡意站點匹配,則network線程發出警報以顯示警告頁面
  • 此外,還會進行跨源讀取阻止(CORB)檢查,以確保敏感的跨站點數據不會進入渲染器進程
    alt
    tips: 響應標頭,其中包含Content-Type和有效載荷,這是實際數據

4. Step4:找到渲染引擎

  • 一旦完成全部檢查,而且Network線程確信瀏覽器應導航到請求的站點,則Network線程將告知UI線程數據已準備就緒。而後,UI線程找到一個渲染器進程來進行網頁渲染
    alt
    tips: network線程告訴UI線程查找渲染器進程
  • 因爲網絡請求可能須要數百毫秒才能得到響應,所以將應用優化來加快此過程。當UI線程在步驟2向網絡線程發送URL請求時,它已經知道他們正在導航到哪一個站點。 UI線程嘗試與網絡請求並行地主動查找或啓動渲染器進程。這樣,若是一切按預期進行,則當網絡線程接收到數據時,渲染器進程已經處於備用位置。若是導航重定向跨站點,則可能不會使用此備用過程,在這種狀況下,可能須要其餘過程

5. Step5:更新導航

  • 如今已經準備好數據和渲染器進程,將IPC從瀏覽器進程發送到渲染器進程以提交導航。它還會傳遞數據流,所以渲染器進程能夠繼續接收HTML數據。一旦瀏覽器進程聽到確認提交已在渲染器進程中完成,導航就完成了,文檔加載階段開始了
  • 此時,地址欄已更新,安全指示符和站點設置UI反映了新頁面的站點信息。標籤的會話歷史記錄將被更新,所以後退/前進按鈕將逐步瀏覽剛剛導航到的站點。爲了在關閉選項卡或窗口時方便選項卡/會話還原,會話歷史記錄存儲在磁盤上
    alt
    tips:瀏覽器和渲染器進程之間的IPC,請求渲染頁面

6. Step6:一旦導航更新之後,渲染引擎拿到了全部資源而後開始渲染頁面。下一節會講。

導航到其餘站點

簡單的導航就完成了!可是,若是用戶再次將不一樣的URL放入地址欄會發生什麼?
瀏覽器過程將經過相同的步驟導航到不一樣的站點。
但在此以前,它須要與當前渲染的站點進行檢查,看看他們是否註冊了beforeunload事件

beforeunload能夠建立「離開此網站?」嘗試導航或關閉選項卡時發出警報。選項卡內的全部內容(包括您的JavaScript代碼)都由渲染器進程處理,所以,當有新的導航請求出現時,瀏覽器進程必須與當前渲染器進程進行覈對

不要添加無條件的beforeunload處理程序。它建立了更多的延遲,由於須要在甚至開始導航以前執行處理程序。僅在須要時才添加此事件處理程序,例如,若是須要警告用戶,他們可能會丟失在頁面上輸入的數據

alt
tips:從瀏覽器進程到渲染器進程的IPC告訴它即將導航到其餘站點

若是導航是從渲染器進程啓動的(例如用戶單擊連接或客戶端JavaScript已運行window.location =「 newsite.com」),則渲染器進程首先檢查beforeunload處理程序。而後,它經歷與瀏覽器過程啓動的導航相同的過程。惟一的區別是導航請求從渲染器進程到瀏覽器進程開始了

當新的導航與當前渲染的站點不在同一個站點上時,將調用一個單獨的渲染過程來處理新的導航,而當前的渲染過程將保留下來以處理諸如卸載之類的事件.

alt
tips: 從瀏覽器進程到新渲染器進程的IPC,告訴渲染頁面並告訴舊渲染器進程卸載

小結

瀏覽器如何渲染一個頁面(六脈神劍):

  1. 處理輸入(Handling input) UI Thread 判斷是search query 仍是 URL
  2. 開始導航(Start navigation)
    • UI Thread 把 URL 給 network Thread
    • DNS && TLS
    • 若是響應的 HTTP碼是 301,拿到的URL傳給UI Thread,更新navigation.從新開啓DNS&&TLS
  3. 讀取響應(Read response: check with response)
    • 拿到響應數據(結果)
    • Network thread 檢查數據是不是從安全站點返回的,若是不是則顯示警告頁
    • Network thread CORB check,檢查跨域問題
    • Network check 響應數據的Content-type
    • 若是是: HTML data --> Renderer process
    • 若是是: zip file or other file --> download manager
  4. 找到渲染引擎(Find a renderer process)
    • UI thread 收到 network thread成功返回數據的信號
    • UI thread 開啓一個 renderer thread
    • (優化==>UI thread拿到URL,傳給network thread之後就直接作開啓renderer process 的準備,等network返回數據完畢後,開的renderer process直接使用)
  5. 更新導航(Commit navigation)
    • network thread 把拿到的數據給 renderer process
    • UI thread receive 收到 renderer process 確認拿到數據的信號
    • navigation completed and the document loading phase begins.
  6. 初始加載完成(Initial load complete)
    • renderer process(loading finished),而後通知browser process
    • UI thread(UI 線程屬於Browser 線程) stops the loading spinner on the tab
  7. 導航到其餘站點
      1. 若是從導航欄輸入其餘站點的URL,先在當前renderer process中去檢查是否有beforeunload事件
    • 2.若是從當前render process內作跳轉,也就是當前頁面腳本中有相似window.href="xxx"這段代碼
      • 首先檢查當前頁面是否有beforeunload事件
      • 1.2點的區別就在於導航請求是從外部(Browser process)仍是內部(Renderer process)發起的。
      1. 當新的導航與當前渲染的站點不在同一個站點上時,將調用一個單獨的渲染過程來處理新的導航,而當前的渲染過程將保留下來以處理諸如卸載unload之類的事件
        這裏涉及到頁面生命週期API能夠參考

alt

3. 瀏覽器內核是如何工做的

4. 瀏覽器如何與用戶交互

相關文章
相關標籤/搜索