當面試官問到,請你說說看“從輸入 URL 到頁面展示,這中間發生了什么?”
以前的我是這樣回答的:
用戶輸入URL后,向服務器端發起請求、如果順利,得到網絡響應之后,瀏覽器對資源進行解析、最后將其渲染到頁面上。
具體步驟為:
-
首先構建請求
-
查找緩存,如果命中緩存,直接使用緩存資源
-
否則進行DNS解析,將域名轉換成對應的IP地址
-
建立TCP連接
-
發送HTTP請求
-
如果順利得到網絡響應,瀏覽器開始解析和渲染
-
HTML解釋器 解析HTML 為 DOM樹
-
同時CSS解釋器 解析CSS文檔 為 styleSheets
-
創建布局樹,進行布局計算
-
整合圖層,展示頁面
乍一看,好像沒什么毛病,但問題就在於,如果面試官針對某個點進行提問,我可能自動切換為一副黑人問號臉,或者是一種【只可意會不可言傳】的沉默表現。
不過沒有關系,學習了李兵老師的《瀏覽器的工作原理與實踐》課程和其他一些參考資料之后,如果再遇到面試官的追問,相信我就可以保持優雅的微笑了。
補充知識
進程與線程
- 進程是CPU資源分配的最小單位(是能擁有資源和獨立運行的最小單位);
- 線程是CPU調度的最小單位(線程是建立在進程的基礎上的一次程序運行單位)。
Chrome 瀏覽器的多進程架構
最新的 Chrome 瀏覽器包括:
- 1 個瀏覽器(Browser)主進程
- 1 個網絡(NetWork)進程
- 1 個 GPU 進程
- 多個渲染進程
- 多個插件進程
這幾個進程的功能:
瀏覽器進程:
- 主要負責界面顯示、用戶交互、子進程管理,同時提供存儲等功能。
網絡進程:
- 主要負責頁面的網絡資源加載,之前是作為一個模塊運行在瀏覽器進程里面的,直至最近才獨立出來,成為一個單獨的進程。
渲染進程:
- 核心任務是將 HTML、CSS 和 JavaScript 轉換為用戶可以與之交互的網頁,排版引擎 Blink 和 JavaScript 引擎 V8 都是運行在該進程中,默認情況下,Chrome 會為每個 Tab 標簽創建一個渲染進程。出於安全考慮,渲染進程都是運行在沙箱模式下。
GPU 進程:
- Chrome 剛開始發布的時候是沒有 GPU 進程的。而 GPU 的使用初衷是為了實現 3D CSS 的效果,只是隨后網頁、Chrome 的 UI 界面都選擇采用 GPU 來繪制,這使得 GPU 成為瀏覽器普遍的需求。最后,Chrome 在其多進程架構上也引入了GPU 進程。
插件進程:
- 主要是負責插件的運行,因插件易崩潰,所以需要通過插件進程來隔離,以保證插件進程崩潰不會對瀏覽器和頁面造成影響。
從輸入 URL 到頁面展示,這中間發生了什么?
有了一些補充知識,我們就可以來看這個問題,從用戶輸入 URL 到頁面展示,這中間的過程可謂是非常地復雜,我將從導航流程和渲染流程來說明,話不多說,直接上流程圖。
導航階段
一個完整的導航流程大致可總結為如下:
- 用戶輸入url並回車;
- 瀏覽器進程檢查url,組裝協議,構成完整的url;
- 瀏覽器進程通過進程間通信(IPC)把url請求發送給網絡進程;
- 網絡進程接收到url請求后檢查本地緩存是否緩存了該請求資源,如果有則將該資源返回給瀏覽器進程;
- 否則查找是否存在DNS緩存,如果沒有,先進行DNS解析,獲取到請求域名對應的服務器IP地址;
- 判斷請求協議是否為HTTPS,如果是,則還需要建立TLS連接;
- 否則,直接建立TCP連接,客戶端通過三次握手與服務端建立連接;
- 瀏覽器向服務器發送HTTP請求;
- 服務器接收到請求信息后,根據請求信息生成響應數據,發給網絡進程;
- 網絡進程解析響應數據;
- 如果響應行的狀態碼包含了 301、302 一類的跳轉信息,瀏覽器會根據響應頭的 Location 字段的地址,進行拼接和跳轉,繼續導航;如果響應行是 200,表示瀏覽器可以繼續處理該請求;
- 如果 Content-Type 字段的值被瀏覽器判斷為下載類型,那么該請求會被提交給瀏覽器的下載管理器,同時該 URL 請求的導航流程就此結束。但如果是HTML,那么瀏覽器則會繼續進行導航流程。
- 瀏覽器為頁面分配渲染進程。打開一個新頁面采用的渲染進程策略就是:通常情況下,打開新的頁面都會使用單獨的渲染進程;如果從 A 頁面打開 B 頁面,且 A 和 B 都屬於同一站點的話,那么 B 頁面復用 A 頁面的渲染進程;如果是其他情況,瀏覽器進程則會為 B 創建一個新的渲染進程。
- 瀏覽器進程向渲染進程發出“提交文檔”的消息,渲染進程接收后,和網絡進程建立傳輸數據的“管道”。 文檔數據傳輸完成之后,渲染進程會返回“確認提交”的消息給瀏覽器進程。瀏覽器進程在收到“確認提交”的消息后,會更新瀏覽器界面狀態,包括了安全狀態、地址欄的 URL、前進后退的歷史狀態,並更新 Web 頁面。
渲染階段
一個完整的渲染流程大致可總結為如下:
- 渲染進程將 HTML 內容轉換為能夠讀懂的DOM 樹結構。
- 渲染引擎將 CSS 樣式表轉化為瀏覽器可以理解的styleSheets,計算出 DOM 節點的樣式。
- 創建布局樹,並計算元素的布局信息。
- 對布局樹進行分層,並生成分層樹。
- 為每個圖層生成繪制列表,並將其提交到合成線程。
- 合成線程將圖層分成圖塊,並在光柵化線程池中將圖塊轉換成位圖。
- 合成線程發送繪制圖塊命令DrawQuad給瀏覽器進程。
- 瀏覽器進程根據 DrawQuad 消息生成頁面,並顯示到顯示器上。
到這里,大功並沒有告成。面試官可能會繼續追問N多個問題,只有好好准備,面試過程才不會顯得那么卑微。
再者,將一個問題能夠理解透徹,也能幫助我們更好地開展今后的工作,畢竟,我們面對的不僅僅是面試。
面試官繼續追問
面試官接着說:可以,對這個過程宏觀上還是把握住了,那我再考察你幾個具體的知識點吧!
瀏覽器相關
- 為什么很多站點第二次打開速度會很快?
- 登錄狀態是如何保持的?
- 瀏覽器中的JavaScript執行機制相關問題
- 。。。
TCP協議
- 能不能說一說三次握手和四次揮手
- 。。。
HTTP協議
- 請說說 HTTP 有哪些狀態碼
- 了解 HTTP/2嗎?相比以前的協議有哪些改進?
- 。。。
參考:HTTP靈魂之問
前端性能優化
- 請你說說瀏覽器緩存
- 什么是瀏覽器的本地存儲呀?
- 你是怎么理解重繪與回流的?
- 針對這一整個過程,你有想過我們可以在哪些方面進行性能優化嗎?
- 。。。
其中涉及到的知識真的太多了,我們確實也需要系統深入的學習,不過在這個金三銀四的求職季,大家如果准備得比較晚,可以挑一些知識點,比如 HTTP 相關、前端性能優化進行深入研究,還有TCP協議中的三次握手和四次揮手,我們肯定也逃不掉,其他的可以先把學習安排往后放一放,如果被問到不會的,可以說不會或者只是簡單了解,記得要保持微笑。