經典面試題:從輸入URL到頁面加載完成之間的過程。你會發現,這題不論大廠小廠,都會問,為什麼? 因為它不僅可以考察面試者的知識廣度還能考察面試者的知識深度。
如果這篇文章有幫助到你,❤️關注+點贊❤️鼓勵一下作者,文章公衆号首發,關注 前端南玖 第一時間擷取最新的文章~
在上一篇文章這些浏覽器面試題,看看你能回答幾個?,我也提到過這個經典面試題。下面我們一起來看看吧~
這個題可以說是面試最常見也是一道可以無限難的題了,一般面試官出這道題就是為了考察你的前端知識的深度與廣度。
1.浏覽器接受URL開啟網絡請求線程(涉及到:浏覽器機制,線程與程序等)
2.開啟網絡線程到發出一個完整的http請求(涉及到:DNS解析,TCP/IP請求,5層網絡協定等)
3.從伺服器接收到請求到對應背景接受到請求(涉及到:負載均衡,安全攔截,背景内部處理等)
4.背景與前台的http互動(涉及到:http頭,響應碼,封包結構,cookie等)
5.緩存問題(涉及到:http強緩存與協商緩存等)(請看上一篇文章這些浏覽器面試題,看看你能回答幾個?)
6.浏覽器接受到http資料包後的解析流程(涉及到html詞法分析,解析成DOM樹,解析CSS生成CSSOM樹,合并生成render渲染樹。然後layout布局,painting渲染,複合圖層合成,GPU繪制,等)
當我們在浏覽器位址欄輸入URL位址後,浏覽器會開一個線程來對我們輸入的URL進行解析處理。
浏覽器程序:負責管理标簽頁的建立銷毀以及頁面的顯示,資源下載下傳等。
第三方插件程序:負責管理第三方插件。
GPU程序:負責3D繪制與硬體加速(最多一個)。
渲染程序:負責頁面文檔解析(HTML,CSS,JS),執行與渲染。(可以有多個)
因為我們在浏覽器中輸入的URL通常是一個域名,并不會直接去輸入IP位址(純粹因為域名比IP好記),但我們的計算機并不認識域名,它隻知道IP,是以就需要這一步操作将域名解析成IP。
protocol:協定頭,比如http,https,ftp等;
host:主機域名或者IP位址;
port:端口号;
path:目錄路徑;
query:查詢的參數;
hash:#後邊的hash值,用來定位某一個位置。
首先會檢視浏覽器<code>DNS</code>緩存,有的話直接使用浏覽器緩存
沒有的話就查詢計算機本地<code>DNS</code>緩存(localhost)
還沒有就詢問遞歸式<code>DNS</code>伺服器(就是網絡提供商,一般這個伺服器都會有自己的緩存)
如果依然沒有緩存,那就需要通過 根域名伺服器 和<code>TLD</code>域名伺服器 再到對應的 權威<code>DNS</code>伺服器 找記錄,并緩存到 遞歸式伺服器,然後 遞歸伺服器 再将記錄傳回給本地
⚠️注意:
DNS解析是非常耗時的,如果頁面中需要解析的域名過多,是非常影響頁面性能的。考慮使用dns與加載或減少DNS解析進行優化。
拿到了IP位址後,就可以發起HTTP請求了。HTTP請求的本質就是TCP/IP的請求建構。建立連接配接時需要3次握手進行驗證,斷開連結也同樣需要4次揮手進行驗證,保證傳輸的<code>可靠性</code>。
第一次握手:用戶端發送位碼為 SYN = 1(SYN 标志位置位),随機産生初始序列号 Seq = J 的資料包到伺服器。伺服器由 SYN = 1(置位)知道,用戶端要求建立聯機。
第二次握手:伺服器收到請求後要确認聯機資訊,向用戶端發送确認号Ack = (用戶端的Seq +1,J+1),SYN = 1,ACK = 1(SYN,ACK 标志位置位),随機産生的序列号 Seq = K 的資料包。
第三次握手:用戶端收到後檢查 Ack 是否正确,即第一次發送的 Seq +1(J+1),以及位碼ACK是否為1。若正确,用戶端會再發送 Ack = (伺服器端的Seq+1,K+1),ACK = 1,以及序号Seq為伺服器确認号J 的确認包。伺服器收到後确認之前發送的 Seq(K+1) 值與 ACK= 1 (ACK置位)則連接配接建立成功。

直白了解:
(用戶端:hello,你是server麼?服務端:hello,我是server,你是client麼 用戶端:yes,我是client 建立成功之後,接下來就是正式傳輸資料。)
用戶端發送一個FIN Seq = M(FIN置位,序号為M)包,用來關閉用戶端到伺服器端的資料傳送。
伺服器端收到這個FIN,它發回一個ACK,确認序号Ack 為收到的序号M+1。
伺服器端關閉與用戶端的連接配接,發送一個FIN Seq = N 給用戶端。
用戶端發回ACK 封包确認,确認序号Ack 為收到的序号N+1。
(主動方:我已經關閉了向你那邊的主動通道了,隻能被動接收了 被動方:收到通道關閉的資訊 被動方:那我也告訴你,我這邊向你的主動通道也關閉了 主動方:最後收到資料,之後雙方無法通信)
1、應用層(DNS,HTTP):DNS解析成IP并發送http請求;
2、傳輸層(TCP,UDP):建立TCP連接配接(3次握手);
3、網絡層(IP,ARP):IP尋址;
4、資料鍊路層(PPP):封裝成幀;
5、實體層(利用實體媒體傳輸比特流):實體傳輸(通過雙絞線,電磁波等各種媒體)。
OSI七層架構:實體層、資料鍊路層、網絡層、傳輸層、會話層、表示層、應用層
HTTP 請求到達伺服器,伺服器進行對應的處理。 最後要把資料傳給浏覽器,也就是傳回網絡響應。
跟請求部分類似,網絡響應具有三個部分:響應行、響應頭和響應體。
不一定。這時候要判斷<code>Connection</code>字段, 如果請求頭或響應頭中包含<code>Connection: Keep-Alive</code>,
表示建立了持久連接配接,這樣TCP連接配接會一直保持,之後請求統一站點的資源會複用這個連接配接。否則斷開TCP連接配接, 請求-響應流程結束。
狀态碼是由3位數組成,第一個數字定義了響應的類别,且有五種可能取值:
1xx:訓示資訊–表示請求已接收,繼續處理。
2xx:成功–表示請求已被成功接收、了解、接受。
3xx:重定向–要完成請求必須進行更進一步的操作。
4xx:用戶端錯誤–請求有文法錯誤或請求無法實作。
5xx:伺服器端錯誤–伺服器未能實作合法的請求。
平時遇到比較常見的狀态碼有:200, 204, 301, 302, 304, 400, 401, 403, 404, 422, 500(分别表示什麼請自行查找)。
請求成功後,伺服器會傳回相應的網頁,浏覽器接收到響應成功的封包後便開始下載下傳網頁,至此,網絡通信結束。
浏覽器在接收到HTML,CSS,JS檔案之後,它是如何将頁面渲染在螢幕上的?
浏覽器在拿到伺服器傳回的網頁之後,首先會根據頂部定義的<code>DTD</code>類型進行對應的解析,解析過程将被交給内部的GUI渲染線程來處理。
DTD(Document Type Definition)文檔類型定義
常見的文檔類型定義
HTML解釋器的工作就是将網絡或者本地磁盤擷取的HTML網頁或資源從位元組流解釋成<code>DOM樹</code>🌲結構
通過上圖可以清楚的了解這一過程:首先是位元組流,經過解碼之後是字元流,然後通過詞法分析器會被解釋成詞語(Tokens),之後經過文法分析器建構成節點,最後這些節點被組建成一顆 DOM 樹。
對于線程化的解釋器,字元流後的整個解釋、布局和渲染過程基本會交給一個單獨的渲染線程來管理(不是絕對的)。由于 DOM 樹隻能在渲染線程上建立和通路,是以建構 DOM 樹的過程隻能在渲染線程中進行。但是,從字元串到詞語這個階段可以交給單獨的線程來做,Chrome 浏覽器使用的就是這個思想。在解釋成詞語之後,Webkit 會分批次将結果詞語傳遞回渲染線程。
這個過程中,如果遇到的節點是 JS 代碼,就會調用 <code>JS引擎</code> 對 JS代碼進行解釋執行,此時由于 <code>JS引擎</code> 和 <code>GUI渲染線程</code> 的互斥,<code>GUI渲染線程</code> 就會被挂起,渲染過程停止,如果 JS 代碼的運作中對DOM樹進行了修改,那麼DOM的建構需要從新開始
如果節點需要依賴其他資源,圖檔/CSS等等,就會調用網絡子產品的資源加載器來加載它們,它們是異步的,不會阻塞目前DOM樹的建構
如果遇到的是 JS 資源URL(沒有标記異步),則需要停止目前DOM的建構,直到 JS 的資源加載并被 <code>JS引擎</code> 執行後才繼續建構DOM
CSS解釋器會将CSS檔案解釋成内部表示結構,生成CSS規則樹,這個過程也是和DOM解析類似的,<code>CSS</code> 位元組轉換成字元,接着詞法解析與法解析,最後構成 <code>CSS對象模型(CSSOM)</code> 的樹結構
等<code>DOM Tree</code>與<code>CSSOM Tree</code>都建構完畢後,接着将它們合并成渲染樹<code>(Render Tree)</code>,<code>渲染樹</code> 隻包含渲染網頁所需的節點,然後用于計算每個可見元素的布局,并輸出給繪制流程,将像素渲染到螢幕上。
計算CSS樣式 ;
建構渲染樹 ;
布局,主要定位坐标和大小,是否換行,各種<code>position overflow z-index</code>屬性 ;
繪制,将圖像繪制出來。
這個過程比較複雜,涉及到兩個概念: reflow(回流)和repain(重繪)。DOM節點中的各個元素都是以盒模型的形式存在,這些都需要浏覽器去計算其位置和大小等,這個過程稱為relow;當盒模型的位置,大小以及其他屬性,如顔色,字型,等确定下來之後,浏覽器便開始繪制内容,這個過程稱為repain。頁面在首次加載時必然會經曆reflow和repain。reflow和repain過程是非常消耗性能的,尤其是在移動裝置上,它會破壞使用者體驗,有時會造成頁面卡頓。是以我們應該盡可能少的減少reflow和repain。
這裡Reflow和Repaint的概念是有差別的:
(1)Reflow:即回流。一般意味着元素的内容、結構、位置或尺寸發生了變化,需要重新計算樣式和渲染樹。
(2)Repaint:即重繪。意味着元素發生的改變隻是影響了元素的一些外觀之類的時候(例如,背景色,邊框顔色,文字顔色等),此時隻需要應用新樣式繪制這個元素就可以了。
回流的成本開銷要高于重繪,而且一個節點的回流往往回導緻子節點以及同級節點的回流, 是以優化方案中一般都包括,盡量避免回流。
回流一定導緻重繪,但重繪不一定會導緻回流
合成(composite)
最後一步合成( <code>composite</code> ),這一步驟浏覽器會将各層資訊發送給GPU,GPU将各層合成,顯示在螢幕上
可以簡單的這樣了解,浏覽器渲染的圖層一般包含兩大類:<code>普通圖層</code>以及<code>複合圖層</code>
首先,普通文檔流内可以了解為一個複合圖層(這裡稱為<code>預設複合層</code>,裡面不管添加多少元素,其實都是在同一個複合圖層中)
其次,absolute布局(fixed也一樣),雖然可以脫離普通文檔流,但它仍然屬于<code>預設複合層</code>。
然後,可以通過<code>硬體加速</code>的方式,聲明一個<code>新的複合圖層</code>,它會單獨配置設定資源
(當然也會脫離普通文檔流,這樣一來,不管這個複合圖層中怎麼變化,也不會影響<code>預設複合層</code>裡的回流重繪)
可以簡單了解下:GPU中,各個複合圖層是單獨繪制的,是以互不影響,這也是為什麼某些場景硬體加速效果一級棒
可以<code>Chrome源碼調試 -> More Tools -> Rendering -> Layer borders</code>中看到,黃色的就是複合圖層資訊。
這些浏覽器面試題,看看你能回答幾個?
這一次帶你徹底了解前端本地存儲
面試官:說一說前端路由與後端路由的差別
JavaScript之原型與原型鍊
Javascript深入之作用域與閉包
this指向與call,apply,bind
覺得文章不錯,可以點個在看呀_另外歡迎留言交流~
作者:前端南玖
出處:https://www.cnblogs.com/songyao666/
-------------------------------------------
個性簽名:智者創造機會,強者把握機會,弱者坐等機會。做一個靈魂有趣的人!
如果覺得這篇文章對你有小小的幫助的話,可以關注下方公衆号,在該公衆号同樣會推送技術文章給大家,謝謝~
歡迎加入前端技術交流群:928029210