JS 頁面載入過程問題

教員的小粉紅~發表於2020-11-22

1. HTML 頁面組成

  • 一個 HTML 頁面是由很多資原始檔組成的
    • 比如最基本的 HTML 本身是一個資源
    • css、js 這些靜態資源
    • 圖片、文字、json 介面等資源
  • 這些資源一般通過 http/https 請求,從伺服器上拿過來

2. 資源載入過程

  1. 第一步,對於一個請求來說,無論是位址列輸入的 url,還是程式碼中載入的 url都要對 url 進行解析提取資訊
  2. 第二步,拿到上一步中解析的域名去 DNS 伺服器上查詢該域名對應的 IP
  3. 第三步,帶著所有的請求資訊去這個 IP 地址上請求資源,然後在伺服器上把返回的資源下載下來
  4. 最後一步,瀏覽器拿到這些資源之後,根據不同的資源型別做不同方式的解析

2.1 URL 解析

在這裡插入圖片描述

  • 請求協議
    • http
    • https
    • ftp
    • tcp
    • 。。。
  • 域名+埠
    • 域名用來查詢伺服器位置
    • 域名就像一個大房子,有一個 IP 地址
    • 等找到這個房子的地址後,就是這個房子的門
    • 一般的協議還有一個預設的埠號
      • 比如 http 協議預設的埠號是 80
      • 比如 https 協議預設的埠號是 443
      • 如果訪問的是預設埠的話,這個埠號是可以省略的
  • 路徑
    • 這個路徑是伺服器接到請求以後,拿著這個路徑在伺服器上定位資源位置的
  • 引數
    • 用來傳遞請求資源的特點
  • 雜湊
    • 前端頁面的錨點
    • 標記頁面位置

2.2 DNS 查詢

  • DNS 域名系統(Domain Name System)
    • DNS 伺服器
    • DNS 快取
2.2.1 DNS 查詢過程
  • 當一個 URL 地址被解析以後,拿到一個域名,但是在網際網路上,資源都是用 IP 地址來訪問的,沒域名什麼事
  • 所以需要把域名轉化成 IP 地址

在這裡插入圖片描述

  • 在 DNS 裡有兩個端
    • 瀏覽器(發起請求)
    • DNS 伺服器(處理查詢請求)
  • 如果所有使用者的每一次請求都去查一下 DNS 伺服器,這個量級是異常巨大的
  • 所以在 DNS 裡有一個很重要的部分,就是 DNS 快取,用來減少 DNS 伺服器上的查詢量
  • 在做 DNS 查詢時,瀏覽器會傳遞一個要解析的域名
    • 比如 www.happymmall.com 傳給 DNS 系統
    • 經過 DNS 查詢,這個域名會對應一個 IP 地址
    • 比如是 97.65.113.212,這就是 www.happymmall.com 的伺服器地址
2.2.2 DNS 查詢場景
  • 場景
    • 小明去新華書店買書,不知道路線
    • 去問張大爺,張大爺也不知道,查詢了地址簿,告訴了小明(相當於 DNS 查詢
    • 不一會,小紅也去新華書店,也不知道路線,也去問張大爺,張大爺直接告訴小紅地址(相當於 DNS 快取
    • 過了一個月,小花也去新華書店,也不知道路線,也去問張大爺,張大爺忘了地址,再去地址簿上查詢,然後告訴小花(這一個月相當於 DNS 快取時間,過期就忘了
2.2.3 DNS 快取
  • DNS 快取並不是一個,而是有很多層
    • 瀏覽器上有
    • 伺服器上有
    • DNS 快取上有
  • 根據不同的網路層級,DNS 快取時間也不一樣
  • 一般越靠近使用者的節點,快取時間越短
    • 比如離使用者最近的瀏覽器一般快取時間是1分鐘或者30秒
    • DNS 根伺服器上的快取時間一般能達到10分鐘
2.2.4 dns-prefetch
<link rel="dns-prefetch" href="//cdn.bootcss.com">
<link rel="dns-prefetch" href="//s.happymmall.com">
<link rel="dns-prefetch" href="//img.happymmall.com">
  • dns-prefetch 原理
    • 在頁面一開始載入時,就會立即把這幾個 href 裡指定的域名做 DNS 查詢並快取起來
    • 等到真正請求這些域名並下載資源的時候,就可以省去 DNS 查詢時間
    • 可以提高頁面的載入速度

2.3 資源請求

2.3.1 資原始檔
  • 這個資源可以是 HTML、CSS、JS、或者介面等資原始檔
  • 可以通過 http 請求得來的任何內容
2.3.2 資源請求過程

在這裡插入圖片描述

  • 資源請求有兩個角色
    • 瀏覽器
    • 後端伺服器
  • 在發起請求時,瀏覽器會帶著一堆資訊,去後端伺服器上尋找資源
  • 這個請求包含兩個部分
    • Request-header 請求頭
      • 裡面包含了很多請求本身的資訊
        • 我需要請求誰
        • 我從哪裡來
        • 我希望得到什麼格式的資料
        • 我用的什麼瀏覽器
        • cookie
    • 請求帶的引數
      • get 請求,引數在 url 裡
      • post 請求,引數在請求的 body 裡
  • 當這些資訊到達伺服器後,伺服器會根據這些到達的資訊,找到匹配的資源,返回給瀏覽器
  • 返回的資訊包括三部分
    • 狀態碼,表示請求結果是否成功
    • Response-header 響應頭,包含響應資訊(文字長度、快取時間、壓縮方式等)
    • 響應內容
      • 如果是圖片,返回的 body 裡就是圖片資訊
      • 如果是介面,返回的 body 裡就是 json 字串
  • 瀏覽器拿到這些響應資訊後,就拿到了自己想要的東西

2.4 瀏覽器解析

2.4.1 DOM 樹
  • 最先載入的是一個 HTML 檔案
  • 在載入 HTML 檔案時,就已經開始構建 DOM 樹
  • 遇到一個 HTML 節點就把它放到 DOM 樹裡
  • 加入在載入一個 HTML 檔案的時候遇到了一個 JS 檔案
  • 那麼構建 DOM 樹的工作就要停下來,先讓 JS 檔案載入和執行
  • JS 檔案有這麼高的優先順序,是因為 JS 檔案能操作 DOM 樹,可能造成之前的 DOM 樹白乾,所以在遇到 JS 檔案的時候,先讓 JS 檔案執行,等 JS 檔案執行完,在接著走
  • JS 檔案執行完後,又構建之前剩下的 DOM 樹
  • 構建 DOM 樹的過程中,如果遇到的是 style 標籤,不會造成阻塞
  • DOM 樹的構建和樣式的載入會並行執行
  • DOM 樹構建完後,就構建渲染樹
2.4.2 渲染樹
  • 渲染樹,是 DOM 樹和樣式表結合的產物
  • 這個渲染樹在各個瀏覽器裡構造的機制也不一樣
    • 比如 Chrome 瀏覽器用的 webkit 核心是在原來的 DOM 樹上附屬一些樣式
    • 而 firefix 裡是根據 DOM 樹和樣式表重新構建出一顆渲染樹出來
  • 渲染樹構建好之後,每個要顯示的元素的大小、佈局方式也就確定了
2.4.3 佈局
  • 接下來就是根據每個元素的大小和佈局方式計算出每個元素的實際位置,這就是佈局的過程
2.4.4 繪製
  • 最後一步繪製
    • 上一步的佈局確定了元素的大小和位置
    • 繪製過程就是呼叫瀏覽器負責顯示的部分,將元素和樣式繪製在對應的螢幕上
      這樣整個瀏覽器的解析過程就完成了

在這裡插入圖片描述

3. 總結

  • 當輸入一個 URL 會發生什麼?
  • 面試問到了,答得不好,記錄一下

相關文章