反直覺!瀏覽器究竟是如何下載資源的

今天文章來聊聊瀏覽器究竟是如何對待下載資源的,好比說 JS、CSS、字體、圖片等文件。javascript

CSS、JS 文件冤家路窄

HTML 在解析的過程當中遇到同步的 script 會卡住 DOM 解析這個知識點我相信讀者們應該都知道。html

<!DOCTYPE html>
<html lang="en">
<body>
    <script>console.log(1)</script>
    <div>1</div>
</body>
</html>
複製代碼

上述代碼中,HTML 遇到 <script>console.log(1)</script> 代碼就會中止 DOM 解析了。固然現代瀏覽器不是說就這樣停住啥也不幹了,會有個 preload scanner 去掃描底下的文件,而後根據文件類型去制定優先級(這個下面再說)。java

上面舉得例子是內聯代碼,若是是一個 JS 文件的話,那麼就得等這個 JS 文件下完之後執行代碼才行。算法

可是通常咱們文件結構不會那麼單一,CSS 文件也確定是有的。由於 JS 不只能動 DOM 也能改 style,因此若是遇到 script 以前還有別的 CSS 文件的話,瀏覽器還得等 CSS 文件下完之後再去執行 JS。瀏覽器

因此說不僅是 JS 會阻塞 DOM 解析,CSS 也會。markdown

固然我想如今應該不多再有人直接寫同步的 script 了吧。網絡

文件同時遇到,那會同時開始下載嘛?

舉個例子,在能夠同時下載多個文件的狀況下,瀏覽器在 HTML、CSS 文件中解析到了 img、font、background-image 資源,那麼們會同時開始下載嘛?併發

答案是不會!dom

這裏只有 img 會最早開始下載,其它兩塊內容都得等到 layout 之後纔會開始下載。不信的話咱們來看圖:svg

這裏以 font 爲例

WechatIMG211

圖中右下角框出來的是字體文件,上面是 CSS 文件,字體是從 CSS 文件中得知須要去加載的。

你們能夠在圖中發現 CSS 文件早早開始下載解析了,可是 font 文件遲遲未開始下載,直到 FP 指標即將出現的時候纔開始下載動做,這個時間點是在 layout 完成之後。

圖中是以掘金爲例,你們能夠多試試別的網站,應該能發現是符合預期的。

那麼讀者可能會有個疑問,按照這個邏輯意思是說能用 img 的都用 img,由於background-image 不是立刻開始下載的?道理是這個道理,可是仍是得分狀況來講,若是圖片出現的位置不是首屏,用 background-image 也沒啥問題,固然給 img 用上懶加載也能解決問題。

那麼到底文件的優先級是如何的?

若是你們有使用過 Performance 測試網站性能的話,能夠在 Network 那欄裏 hover 下載的資源,此時你能發現資源有優先級的顯示。

2151614520163_.pic 2171614520185_.pic 2141614520153_.pic 2161614520170_.pic 2181614520195_.pic

從圖中你們能夠發現 CSS 和字體資源的優先級的最高的,JS 文件有高有低(這和類型有關),圖片、svg 的優先級爲低。

這部分的優先級是指某個時間點上的優先級,而不是適應於整個週期。對於 CSS 文件優先級最高仍是挺好理解的,畢竟 JS 文件依賴於 CSS 文件,更加詳細的內容你們能夠參考 從Chrome源碼看瀏覽器如何加載資源 中的「3. 資源優先級」內容。

網絡協議纔是最大元兇

瀏覽器要下載資源,TCP 協議確定得用上,可是 TCP 協議天生就是一個慢的東西。

先得握手,而後慢開始算法,就和咱們用迅雷下載東西同樣,帶寬很大沒用,速度都是得爬升上去的。若是再加個 HTTPS 的話,還得再多個 TLS 的握手。

而後說回 HTTP1.1 協議。Chrome 只支持同個 domain 同時併發 6 個請求,因此在以前的協議中一堆請求都得 block 住等以前的下載完成。

固然如今不一樣了,HTTP2 的概念基本你們都知道了,沒見過豬跑但吃過豬肉,對於這塊的知識點聊上幾句沒啥問題。什麼多路複用,header 合併、二進制幀啥的。

得利於 HTTP2 協議中的多路複用,咱們再也不被瀏覽器的六個併發所限制,全部同一個 domain 上的請求都能跑在複用的六個網絡通道上,下載耗時瞬間減小了幾個量級,可是你們有沒有考慮過這個 HTTP2 究竟是如何對待這些資源的?

如何分配它們的優先級?依賴?帶寬或者別的?畢竟一堆資源佔用同一個網絡通道,那麼到底該誰先下載,誰享有的帶寬多點都是須要協調的。不然假如一堆圖片佔用了大部分帶寬,其餘 CSS、JS 文件下的很慢的話,就會影響整個網頁的性能了。

好比說我如今須要下載 CSS、JS、圖片和字體這些文件。舉個例子在這些文件中我但願 CSS 文件能最早開始下載,而且能分配到的帶寬多點;JS 文件呢能夠等 CSS 文件下完再去下;其餘文件呢優先級比 CSS 文件低點,可是也可以享受到帶寬去進行下載。

這個需求咱們能夠經過二進制幀去實現。HTTP2 協議共存在十個二進制幀,其中你能夠經過 HEADERS 幀分配新的優先級,也能夠經過 PRIORITY 幀更改優先級。

對於流的優先級,咱們能夠經過兩個方式來實現調整:

  • 當咱們調整流的依賴時,就能夠實現讓 JS 文件等待 CSS 文件下載完畢之後再開始
  • 當咱們調整流的 weight 時,就能夠實現帶寬的分配,讓某些資源能更快地進行下載

WX20210228-223401@2x

如圖所示(醜了點)。第一排的文件開始一塊兒下載,weight 相加爲 20,那麼經過計算可得 CSS 文件享有帶寬的一半,其餘各佔有 1 / 4,JS 文件得等 CSS 完成之後纔開始。

那麼該如何設置這些東西呢?固然得服務端支持啦,通常都指 CDN 服務商了。

最後

以上就是所有內容了,你們有想探討的能夠一塊兒交流。

相關文章
相關標籤/搜索