1. 程式人生 > >從輸入url到頁面載入完成發生了什麼?

從輸入url到頁面載入完成發生了什麼?

  這是一道經典的面試題,這道面試題不光前端面試會問到,後端面試也會被問到。這道題沒有一個標準的答案,它涉及很多的知識點,面試官會通過這道題了解你對哪一方面的知識比較擅長,然後繼續追問看看你的掌握程度。當然我寫的這些也只是我的一些簡單的理解,從前端的角度出發,我覺得首先回答必須包括幾個基本的點,然後在根據你的理解深入回答。

  1、瀏覽器的位址列輸入URL並按下回車。

  2、瀏覽器查詢當前URL是否存在快取,並比較快取是否過期。

  3、DNS解析URL對應的IP。

  4、根據IP建立TCP連線(三次握手)。

  5、HTTP發起請求。

  6、伺服器處理請求,瀏覽器接收HTTP響應。

  7、渲染頁面,構建DOM樹。

  8、關閉TCP連線(四次揮手)。

  說完整個過程的幾個關鍵點後我們再來展開的說一下。

  一、URL

  我們常見的RUL是這樣的:http://www.baidu.com,這個域名由三部分組成:協議名、域名、埠號,這裡埠是預設所以隱藏。除此之外URL還會包含一些路徑、查詢和其他片段,例如:http://www.tuicool.com/search?kw=%E4%。我們最常見的的協議是HTTP協議,除此之外還有加密的HTTPS協議、FTP協議、FILe協議等等。URL的中間部分為域名或者是IP,之後就是埠號了。通常埠號不常見是因為大部分的都是使用預設埠,如HTTP預設埠80,HTTPS預設埠443。說到這裡可能有的面試官會問你同源策略,以及更深層次的跨域的問題,我今天就不在這裡展開了。

  二、快取

  說完URL我們說說瀏覽器快取,HTTP快取有多種規則,根據是否需要重新向伺服器發起請求來分類,我將其分為強制快取,對比快取。

  強制快取判斷HTTP首部欄位:cache-control,Expires。

  Expires是一個絕對時間,即伺服器時間。瀏覽器檢查當前時間,如果還沒到失效時間就直接使用快取檔案。但是該方法存在一個問題:伺服器時間與客戶端時間可能不一致。因此該欄位已經很少使用。

  cache-control中的max-age儲存一個相對時間。例如Cache-Control: max-age = 484200,表示瀏覽器收到檔案後,快取在484200s內均有效。 如果同時存在cache-control和Expires,瀏覽器總是優先使用cache-control。

  對比快取通過HTTP的last-modified,Etag欄位進行判斷。

  last-modified是第一次請求資源時,伺服器返回的欄位,表示最後一次更新的時間。下一次瀏覽器請求資源時就傳送if-modified-since欄位。伺服器用本地Last-modified時間與if-modified-since時間比較,如果不一致則認為快取已過期並返回新資源給瀏覽器;如果時間一致則傳送304狀態碼,讓瀏覽器繼續使用快取。

  Etag:資源的實體標識(雜湊字串),當資源內容更新時,Etag會改變。伺服器會判斷Etag是否發生變化,如果變化則返回新資源,否則返回304。

  

  三、DNS域名解析

  我們知道在位址列輸入的域名並不是最後資源所在的真實位置,域名只是與IP地址的一個對映。網路伺服器的IP地址那麼多,我們不可能去記一串串的數字,因此域名就產生了,域名解析的過程實際是將域名還原為IP地址的過程。

  首先瀏覽器先檢查本地hosts檔案是否有這個網址對映關係,如果有就呼叫這個IP地址對映,完成域名解析。

  如果沒找到則會查詢本地DNS解析器快取,如果查詢到則返回。

  如果還是沒有找到則會查詢本地DNS伺服器,如果查詢到則返回。

  最後迭代查詢,按根域伺服器 ->頂級域,.cn->第二層域,hb.cn ->子域,www.hb.cn的順序找到IP地址。

  

  遞迴查詢,按上一級DNS伺服器->上上級->....逐級向上查詢找到IP地址。

  

  四、TCP連線

在通過第一步的DNS域名解析後,獲取到了伺服器的IP地址,在獲取到IP地址後,便會開始建立一次連線,這是由TCP協議完成的,主要通過三次握手進行連線。

  第一次握手: 建立連線時,客戶端傳送syn包(syn=j)到伺服器,並進入SYN_SENT狀態,等待伺服器確認; 

  第二次握手: 伺服器收到syn包,必須確認客戶的SYN(ack=j+1),同時自己也傳送一個SYN包(syn=k),即SYN+ACK包,此時伺服器進入SYN_RECV狀態;

  第三次握手: 客戶端收到伺服器的SYN+ACK包,向伺服器傳送確認包ACK(ack=k+1),此包傳送完畢,客戶端和伺服器進入ESTABLISHED(TCP連線成功)狀態,完成三次握手。

  完成三次握手,客戶端與伺服器開始傳送資料。

  

  五、瀏覽器向伺服器傳送HTTP請求

  完整的HTTP請求包含請求起始行、請求頭部、請求主體三部分。

  

  六、瀏覽器接收響應

  伺服器在收到瀏覽器傳送的HTTP請求之後,會將收到的HTTP報文封裝成HTTP的Request物件,並通過不同的Web伺服器進行處理,處理完的結果以HTTP的Response物件返回,主要包括狀態碼,響應頭,響應報文三個部分。

  狀態碼主要包括以下部分

  1xx:指示資訊–表示請求已接收,繼續處理。

  2xx:成功–表示請求已被成功接收、理解、接受。

  3xx:重定向–要完成請求必須進行更進一步的操作。

  4xx:客戶端錯誤–請求有語法錯誤或請求無法實現。

  5xx:伺服器端錯誤–伺服器未能實現合法的請求。

  響應頭主要由Cache-Control、 Connection、Date、Pragma等組成。

  響應體為伺服器返回給瀏覽器的資訊,主要由HTML,css,js,圖片檔案組成。

  七、頁面渲染

  如果說響應的內容是HTML文件的話,就需要瀏覽器進行解析渲染呈現給使用者。整個過程涉及兩個方面:解析和渲染。在渲染頁面之前,需要構建DOM樹和CSSOM樹。

  

  在瀏覽器還沒接收到完整的 HTML 檔案時,它就開始渲染頁面了,在遇到外部鏈入的指令碼標籤或樣式標籤或圖片時,會再次傳送 HTTP 請求重複上述的步驟。在收到 CSS 檔案後會對已經渲染的頁面重新渲染,加入它們應有的樣式,圖片檔案載入完立刻顯示在相應位置。在這一過程中可能會觸發頁面的重繪或重排。這裡就涉及了兩個重要概念:Reflow和Repaint。

  Reflow,也稱作Layout,中文叫回流,一般意味著元素的內容、結構、位置或尺寸發生了變化,需要重新計算樣式和渲染樹,這個過程稱為Reflow。

  Repaint,中文重繪,意味著元素髮生的改變只是影響了元素的一些外觀之類的時候(例如,背景色,邊框顏色,文字顏色等),此時只需要應用新樣式繪製這個元素就OK了,這個過程稱為Repaint。

  所以說Reflow的成本比Repaint的成本高得多的多。DOM樹裡的每個結點都會有reflow方法,一個結點的reflow很有可能導致子結點,甚至父點以及同級結點的reflow。

  下面這些動作有很大可能會是成本比較高的:

  • 增加、刪除、修改DOM結點時,會導致Reflow或Repaint

  • 移動DOM的位置,或是搞個動畫的時候

  • 內容發生變化

  • 修改CSS樣式的時候

  • Resize視窗的時候(移動端沒有這個問題),或是滾動的時候

  • 修改網頁的預設字型時

  基本上來說,reflow有如下的幾個原因:

  • Initial,網頁初始化的時候

  • Incremental,一些js在操作DOM樹時

  • Resize,其些元件的尺寸變了

  • StyleChange,如果CSS的屬性發生變化了

  • Dirty,幾個Incremental的reflow發生在同一個frame的子樹上

  八、關閉TCP連線或繼續保持連線

  通過四次揮手關閉連線(FIN ACK, ACK, FIN ACK, ACK)。

  

  第一次揮手是瀏覽器發完資料後,傳送FIN請求斷開連線。

  第二次揮手是伺服器傳送ACK表示同意,如果在這一次伺服器也傳送FIN請求斷開連線似乎也沒有不妥,但考慮到伺服器可能還有資料要傳送,所以伺服器傳送FIN應該放在第三次揮手中。

  這樣瀏覽器需要返回ACK表示同意,也就是第四次揮手。

  至此從瀏覽器位址列輸入URL到頁面呈現到你面前的整個過程就分析完了,上面內容如有錯誤歡迎留言交流。