本系列分4個部分來說述Chrome瀏覽器是如何工做的。
若是你想知道瀏覽器如何將你寫好的代碼(HTML/CSS/JAVASCRIPT)變成你所看到的網頁這一過程所發生的細節,那麼本文章適合你。面試
目錄以下
- Chrome瀏覽器的架構
- 介紹計算機的核心術語以及Chrome瀏覽器的架構--->【多進程多線程架構】
- 瀏覽器如何展現一個頁面
從瀏覽器的【導航欄(UI Thread)】出發,深挖在【多進程多線程】的架構下
各個進程 :: Process
各個線程 :: Thread
之間如何【通訊】
------⏬------
來最終展現網頁
複製代碼
- 瀏覽器內核是如何工做的
- Chrome瀏覽器內核---> 渲染進程(Renderer)是如何工做的
- 瀏覽器如何與用戶交互
1. Chrome瀏覽器的架構
準備工做
瀏覽器是一個應用程序(Application),在一個計算機上運行一個應用程序,都須要哪些東西呢?
最基本的3點(把大象裝冰箱):chrome
- 硬件(Machine Hardware)
- 操做系統(Operating System)
- 應用程序(Application)
tips: 計算機體系結構的三層。機器硬件在底部,操做系統在中間,應用程序在頂部
瀏覽器的工做離不開硬件和操做系統的支持,關於這塊,咱們須要知道的知識有:跨域
- CPU (中央處理器)
- GPU (圖形處理單元)
- Process (進程)
- Thread (線程)
這裏能夠作一個簡單的解釋(看圖說話)
具體細節能夠自行去了解,特別是進程與線程的概念。瀏覽器
- CPU && GPU
- Process && Thread
正式開始
知道了進程和線程的概念。
那麼如何使用進程和線程構建Web瀏覽器呢?
其實答案並非惟一的安全
- 可使用一個進程包含許多線程(圖左👈)
- 多個進程,每一個進程包含一些線程,進程之間相互通訊(圖右👉)
這裏咱們研究的是最近的架構,即多進程多線程架構。
bash
如圖所示。
瀏覽器的主要進程有:
- Browser Process
- 控制應用程序的chrome部分,包括地址欄、書籤、後退和前進按鈕(UI thread)
- 處理Web瀏覽器一些UI上未顯示的功能,例如網絡請求和文件訪問等(network thread)
- Renderer Process
- Plugin Process
- GPU Process
- 與其餘進程隔離地處理GPU任務。GPUs處理來自多個不一樣應用程序的請求並把它們畫在屏幕上
其中最頂部是【Browser Process】,其負責協調應用程序的其餘進程。
對於渲染進程【Renderer Process】,每個Tab欄均可理解爲建立了一個渲染進程。網絡
整個瀏覽器還有其餘的進程,例如Extension process 和 utility process。
具體查看瀏覽器運行的時候都開啓了哪些進程,能夠點擊右上角的:按鈕,選擇【更多工具】,點擊【任務管理器】。這裏能夠看到瀏覽器開啓的全部進程。多線程
瀏覽器多進程多架構的好處
有哪些好處其實隨便想一想就有不少(暫不詳述)。架構
- 單個頁面崩潰不會影響其餘頁面
- 安全性
- 健壯性
節約內存
Chrome正在進行架構更改,以將瀏覽器程序的每一個部分做爲一項服務運行,從而能夠輕鬆拆分爲不一樣的進程或整合爲一個進程。
工具
站點隔離
網站隔離是Chrome最近引入的功能,可爲每一個跨網站iframe運行單獨的渲染器進程。 自Chrome 67起,默認狀況下在桌面上啓用了網站隔離功能,標籤中的每一個跨網站iframe都會得到一個單獨的渲染器進程(可經過chrome內部的【任務管理器】查看)
小結
本節只須要理解:
- Chrome瀏覽器是多進程多線程架構的
- Chrome瀏覽器的主要進程有
- Browser Process(負責統籌全局)
- GPU Process(負責圖像處理)
- Plugin Process(負責運行插件)
- Renderer Process(負責渲染頁面)
- Chrome瀏覽器多進程多架構的好處
- 站點隔離
2. 瀏覽器如何展現一個頁面
有一道很常見的面試題: 【從地址欄輸入url都發生了什麼】
咱們就從瀏覽器的導航開始,從瀏覽器的地址欄輸入url,都發生了什麼:
從 Browser process開始
- 當地址欄中輸入URL時,輸入將由瀏覽器進程的UI線程處理
Step1: 處理輸入
- 瀏覽器會判斷你在地址欄的輸入是一個搜索查詢仍是一個URL,以便決定是將你的輸入放入搜索引擎去查詢,仍是幫你發送一個網頁請求。
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文件或其餘文件,則意味着這是下載請求,所以他們須要將數據傳遞到下載管理器
- network線程從安全站點詢問響應數據是否爲HTML
- 這也是進行安全瀏覽檢查的地方
- 若是域和響應數據與已知的惡意站點匹配,則network線程發出警報以顯示警告頁面
- 此外,還會進行跨源讀取阻止(CORB)檢查,以確保敏感的跨站點數據不會進入渲染器進程
tips: 響應標頭,其中包含Content-Type和有效載荷,這是實際數據
4. Step4:找到渲染引擎
- 一旦完成全部檢查,而且Network線程確信瀏覽器應導航到請求的站點,則Network線程將告知UI線程數據已準備就緒。而後,UI線程找到一個渲染器進程來進行網頁渲染
tips: network線程告訴UI線程查找渲染器進程
- 因爲網絡請求可能須要數百毫秒才能得到響應,所以將應用優化來加快此過程。當UI線程在步驟2向網絡線程發送URL請求時,它已經知道他們正在導航到哪一個站點。 UI線程嘗試與網絡請求並行地主動查找或啓動渲染器進程。這樣,若是一切按預期進行,則當網絡線程接收到數據時,渲染器進程已經處於備用位置。若是導航重定向跨站點,則可能不會使用此備用過程,在這種狀況下,可能須要其餘過程
5. Step5:更新導航
- 如今已經準備好數據和渲染器進程,將IPC從瀏覽器進程發送到渲染器進程以提交導航。它還會傳遞數據流,所以渲染器進程能夠繼續接收HTML數據。一旦瀏覽器進程聽到確認提交已在渲染器進程中完成,導航就完成了,文檔加載階段開始了
- 此時,地址欄已更新,安全指示符和站點設置UI反映了新頁面的站點信息。標籤的會話歷史記錄將被更新,所以後退/前進按鈕將逐步瀏覽剛剛導航到的站點。爲了在關閉選項卡或窗口時方便選項卡/會話還原,會話歷史記錄存儲在磁盤上
tips:瀏覽器和渲染器進程之間的IPC,請求渲染頁面
6. Step6:一旦導航更新之後,渲染引擎拿到了全部資源而後開始渲染頁面。下一節會講。
導航到其餘站點
簡單的導航就完成了!可是,若是用戶再次將不一樣的URL放入地址欄會發生什麼?
瀏覽器過程將經過相同的步驟導航到不一樣的站點。
但在此以前,它須要與當前渲染的站點進行檢查,看看他們是否註冊了beforeunload事件
beforeunload能夠建立「離開此網站?」嘗試導航或關閉選項卡時發出警報。選項卡內的全部內容(包括您的JavaScript代碼)都由渲染器進程處理,所以,當有新的導航請求出現時,瀏覽器進程必須與當前渲染器進程進行覈對
不要添加無條件的beforeunload處理程序。它建立了更多的延遲,由於須要在甚至開始導航以前執行處理程序。僅在須要時才添加此事件處理程序,例如,若是須要警告用戶,他們可能會丟失在頁面上輸入的數據
tips:從瀏覽器進程到渲染器進程的IPC告訴它即將導航到其餘站點
若是導航是從渲染器進程啓動的(例如用戶單擊連接或客戶端JavaScript已運行window.location =「 newsite.com」),則渲染器進程首先檢查beforeunload處理程序。而後,它經歷與瀏覽器過程啓動的導航相同的過程。惟一的區別是導航請求從渲染器進程到瀏覽器進程開始了
當新的導航與當前渲染的站點不在同一個站點上時,將調用一個單獨的渲染過程來處理新的導航,而當前的渲染過程將保留下來以處理諸如卸載之類的事件.
tips: 從瀏覽器進程到新渲染器進程的IPC,告訴渲染頁面並告訴舊渲染器進程卸載
小結
瀏覽器如何渲染一個頁面(六脈神劍):
- 處理輸入(Handling input) UI Thread 判斷是search query 仍是 URL
- 開始導航(Start navigation)
- UI Thread 把 URL 給 network Thread
- DNS && TLS
- 若是響應的 HTTP碼是 301,拿到的URL傳給UI Thread,更新navigation.從新開啓DNS&&TLS
- 讀取響應(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
- 找到渲染引擎(Find a renderer process)
- UI thread 收到 network thread成功返回數據的信號
- UI thread 開啓一個 renderer thread
- (優化==>UI thread拿到URL,傳給network thread之後就直接作開啓renderer process 的準備,等network返回數據完畢後,開的renderer process直接使用)
- 更新導航(Commit navigation)
- network thread 把拿到的數據給 renderer process
- UI thread receive 收到 renderer process 確認拿到數據的信號
- navigation completed and the document loading phase begins.
- 初始加載完成(Initial load complete)
- renderer process(loading finished),而後通知browser process
- UI thread(UI 線程屬於Browser 線程) stops the loading spinner on the tab
- 導航到其餘站點
-
- 若是從導航欄輸入其餘站點的URL,先在當前renderer process中去檢查是否有beforeunload事件
- 2.若是從當前render process內作跳轉,也就是當前頁面腳本中有相似window.href="xxx"這段代碼
- 首先檢查當前頁面是否有beforeunload事件
- 1.2點的區別就在於導航請求是從外部(Browser process)仍是內部(Renderer process)發起的。
-
- 當新的導航與當前渲染的站點不在同一個站點上時,將調用一個單獨的渲染過程來處理新的導航,而當前的渲染過程將保留下來以處理諸如卸載unload之類的事件
這裏涉及到頁面生命週期API能夠參考
3. 瀏覽器內核是如何工做的
4. 瀏覽器如何與用戶交互