當在瀏覽器輸入URL回車後,瀏覽器到底做了什麼?瀏覽器渲染機制又是怎樣的?

常好樂發表於2017-10-25

當輸入一個網址,瀏覽器到底做了什麼?

當你輸入一個URL也就是一個網址,瀏覽器到底發生了什麼,這種問題既是老生常談,對於新手來說也是面試考察重點,這是瞭解前端瀏覽器網通訊機制的很重要的一步驟。在這裡想用自己總結出來的一套文字來說明一下這個問題。

那麼,我們輸入網址後,實際發生了什麼呢?過程如下:

一、輸入一個網址
二、瀏覽器通過訪問這個網址URL(也可以叫做域名(DN)之後有對域名DN和URL的區別解釋,這裡視為一樣)利用域名系統(DNS)查詢域名的IP地址。
在查詢過程中事實上 ,瀏覽器會先去檢索一些快取地帶,具體快取地帶如下:

  • 瀏覽器快取 – 瀏覽器會快取DNS記錄一段時間。(2分鐘到30分鐘不等)。
  • 系統快取 – 如果在瀏覽器快取裡沒有找到需要的記錄,瀏覽器會在作業系統中去檢索DNS快取記錄。
  • 作業系統中HOST檔案 – 如果在系統快取裡沒找到,則繼續檢索系統的HOST檔案去找到有沒有DNS快取記錄。
  • 如果在作業系統中也沒有發現快取DNS記錄,則作業系統將這個域名傳送至LDNS(本地域名伺服器系統,如果你是電信網,LDNS就在電信那裡)LDNS查詢自己的快取(可以說一般絕對大多數情況都能在這裡查到),如果查詢成功則返回結果,如果查詢失敗則發起一次迭代DNS解析請求。
    如果最終的是在LDNS裡找到記錄的話,則會實現以下步驟:
    1. LDNS向Root Name Server發起請求,此處,Root Name Server返回com域的頂級域名伺服器地址。
    2. LDNS向com域的頂級域名伺服器發起請求,返回baidu.com域名伺服器地址;
    3. LDNS向baidu.com域名伺服器發起請求,得到www.baidu.com的IP地址。
    4. LDNS將得到的IP地址返回給作業系統,同時作業系統自己也將把這個IP地址儲存起來,方便以後使用。
    5. 作業系統將IP地址返回給瀏覽器,同時瀏覽器自己也將把這個IP地址儲存起來,方便以後使用。
    6. 至此,瀏覽器已得到域名對應的IP地址了。
      補充說明:
  • 域名(DN)和URL是有區別的。域名是一臺或一組伺服器的名稱,用來確定伺服器的位置;URL是統一資源定位符,用來確認某一檔案的具體位置。例如:bilibili.com是嗶哩嗶哩的域名(DN),但bilibili.com/video/av15690032/ 是URL,可以見得URL其實是域名(DN)的伺服器裡一個具體檔案的地址。
  • IP地址和域名(DN)也不是一一對應的。可以把多個提供相同服務的伺服器IP設定成為同一個域名(DN)下。但同一時刻,一個域名(DN)只能解析出一個IP地址。也就是說,我們在輸入一個域名bilibili.com時,有可能其背後有多個IP地址,具體分配到哪一個IP地址論情況而定,但最終肯定只會分配到某一個IP地址裡去。

    建立連線 三次握手

    知道伺服器IP地址後,下面就開始客戶端瀏覽器和伺服器建立連線了:
    1.主機向伺服器傳送一個建立連結的請求(你好,約嗎!)
    2.伺服器接受到請求後傳送同意連線的訊號(你好,約!)
    3.主機接收到同意訊號後,再次向伺服器傳送確認訊號(很高興能約到你!)。自此,主機與伺服器建立了連線。
    注:三次握手採用TCP協議,起可以保證資訊傳輸的可靠性,三次握手中,如果有一方沒接收到確認訊號,協議會要求重新傳送訊號。

三、建立連線成功後,瀏覽器就給伺服器傳送一個HTTP請求
四、網站服務的永久重定向響應。
解釋:伺服器給瀏覽器響應一個301永久重定向響應,為什麼伺服器一定要重定向而不是直接發會使用者想看的網頁內容呢?其中一個原因跟搜尋引擎排名有關。如果一個頁面有兩個地址,就像www.bilibili.com/bilibili.com/ 搜尋引擎會認為它們是兩個網站,結果造成每一個的搜尋連結都減少從而降低排名。而搜尋引擎知道301永久重定向是什麼意思,這樣就會把訪問帶www的和不帶www的地址歸到同一個網站排名下。還有一個是用不同的地址會造成快取友好性變差。當一個頁面有好幾個名字時,它可能會在快取裡出現好幾次。
五、瀏覽器跟蹤重定向響應地址。
六、伺服器處理請求
七、瀏覽器返回需要請求的HTML檔案
八、瀏覽器開始載入HTML檔案,渲染並顯示在瀏覽器上。
九、在載入HTML檔案中,一定在HTML檔案中有其他需要載入的圖片或者JS、css檔案等等,然後瀏覽器繼續發出請求,並載入他們,嵌入到HTML檔案中去。

瀏覽器渲染機制又是怎樣的?

在我們輸入一個URL點選回車,瀏覽器大致就做了這些事情。在上面的第八的一個步驟,提及到渲染年並顯示到瀏覽器上,那麼這樣的渲染過程又是怎樣實現的呢?
瀏覽器渲染的基本流程如下:
解析HTML檔案構建DOM樹->構建render樹->佈局render樹->繪製render樹

  1. 首先瀏覽器會將HTML檔案解析成DOM樹,DOM樹的構建過程是一個深度遍歷的過程,也就是說當所有子節點佈置好了後才會去佈置這個子節點的兄弟節點。
  2. 然後將CSS構建成CSS規則樹。
  3. 根據DOM樹和CSS規則樹來構建Render樹(在Render樹中不會出現header標籤或display:none的標籤)。生成Render樹時瀏覽器是不知道各個節點子瀏覽器中的具體位置的。
  4. 然後進入佈局(layout)render樹。佈局並確定每個節點在瀏覽器中的真正位置,寬,高,顏色等。
  5. 最後一步就是繪製render樹,瀏覽器將佈局好的render樹繪製畫出來。

    上面的過程是一步一步完成的。但是,瀏覽器會了提高效率,並不是等所有的HTML檔案解析成DOM樹再進行渲染和佈局的,而是先解析完一部分,就緊接著渲染,再解析餘下的部分。

    關於渲染機制的兩個概念:
    reflow(重排、迴流):在瀏覽器進行第4項layout佈局render樹過程時,其實瀏覽器就在做reflow的操作。佈局是要花時間的,當瀏覽器發現某個部分的變化影響了佈局(改變寬,高,刪除,新增節點,移動節點佈局位置,修改瀏覽器預設字型,resize瀏覽器視窗),需要倒回去重新佈局,這個過程叫reflow。
    repaint(重繪):在瀏覽器進行第5項繪製render樹時其實就是進行的repaint操作,在瀏覽器佈局render樹完成之後,佈局不會再發生改變,僅僅發生一些繪製上的改變(例如改變背景顏色或字型顏色),則需要重新繪製畫畫。
    所以:迴流必將引起重繪,而重繪不一定會引起迴流。
    reflow和repaint都是無法避免的。我們只能夠儘可能少地去避免過多的reflow和repaint。
    避免reflow和repaint的方法:

    1. 絕對定位,position:absolute或position:fixed。這樣,元素就脫離了文件流,它的變化不會影響到其他元素佈局。不過絕對佈局喪失了許多靈活性。
    2. 在JS裡不要一條一條去修改CSS樣式的屬性的值,應該預先寫好需要的css的各個樣式屬性的值,做一個命名,然後只需要修改 DOM 的 className的命名就可以了。
      // 不好的寫法
      var left = 10,
      top = 10;
      el.style.left = left + "px";
      el.style.top  = top  + "px";
      el.style.background = '#eee'; 
      // 比較好的寫法
      el.className += " theclassname";複製程式碼
    3. 不要用tables佈局。
    4. 避免使用CSS的JS表示式
    5. 不要把DOM節點的屬性值拿到迴圈體裡面去做迴圈,最好是先儲存好這個屬性值,再去做迴圈。

HTML頁面載入和解析流程

  1. 使用者輸入網址(假設是個html頁面,並且是第一次訪問),瀏覽器向伺服器發出請求,伺服器返回html檔案;
  2. 瀏覽器開始載入html程式碼,發現<head>標籤內有一個<link>標籤引用外部CSS檔案;
  3. 瀏覽器又發出CSS檔案的請求,伺服器返回這個CSS檔案;
  4. 瀏覽器繼續載入html中<body>部分的程式碼,並且CSS檔案已經拿到手了,可以開始渲染頁面了;
  5. 瀏覽器在程式碼中發現一個<img>標籤引用了一張圖片,向伺服器發出請求。此時瀏覽器不會等到圖片下載完,而是繼續渲染後面的程式碼;
  6. 伺服器返回圖片檔案,由於圖片佔用了一定面積,影響了後面段落的排布,因此瀏覽器需要回過頭來重新渲染這部分程式碼;
  7. 瀏覽器發現了一個包含一行Javascript程式碼的<script>標籤,趕快執行它;
  8. Javascript指令碼執行了這條語句,它命令瀏覽器隱藏掉程式碼中的某個<div> (style.display=”none”)。突然少了這麼一個元素,瀏覽器不得不重新渲染這部分程式碼;
  9. 終於等到了</html>的到來,瀏覽器淚流滿面……
  10. 等等,還沒完,使用者點了一下介面中的“換膚”按鈕,Javascript讓瀏覽器換了一下<link>標籤的CSS路徑;
  11. 瀏覽器召集了在座的各位<div><span><ul><li>們,“大夥兒收拾收拾行李,我們得重新來過……”,瀏覽器向伺服器請求了新的CSS檔案,重新渲染頁面。

相關文章