入門 基礎知識點:瀏覽器到底是如何下載資源的

天文章來聊聊瀏覽器到底是如何對待下載資源的,比如說 JS、CSS、字型、圖片等檔案。

CSS、JS 檔案冤家路窄

HTML 在解析的過程中遇到同步的

script

會卡住 DOM 解析這個知識點我相信讀者們應該都知道。

<!DOCTYPE html>

1

上述程式碼中,HTML 遇到

程式碼就會停止 DOM 解析了。當然現代瀏覽器不是說就這樣停住啥也不幹了,會有個 preload scanner 去掃描底下的檔案,然後根據檔案型別去制定優先順序(這個下面再說)。

上面舉得例子是內聯程式碼,如果是一個 JS 檔案的話,那麼就得等這個 JS 檔案下完以後執行程式碼才行。

但是一般我們檔案結構不會那麼單一,CSS 檔案也肯定是有的。因為 JS 不僅能動 DOM 也能改 style,所以如果遇到

script

之前還有別的 CSS 檔案的話,瀏覽器還得等 CSS 檔案下完以後再去執行 JS。

所以說不只是 JS 會阻塞 DOM 解析,CSS 也會。

當然我想現在應該很少再有人直接寫同步的

script

了吧。

檔案同時遇到,那會同時開始下載嘛?

舉個例子,在可以同時下載多個檔案的情況下,瀏覽器在 HTML、CSS 檔案中解析到了 img、font、background-image 資源,那麼們會同時開始下載嘛?

答案是不會!

這裡只有 img 會最先開始下載,其它兩塊內容都得等到 layout 以後才會開始下載。不信的話我們來看圖:

這裡以 font 為例

入門 基礎知識點:瀏覽器到底是如何下載資源的

圖中右下角框出來的是字型檔案,上面是 CSS 檔案,字型是從 CSS 檔案中得知需要去載入的。

大家可以在圖中發現 CSS 檔案早早開始下載解析了,但是 font 檔案遲遲未開始下載,直到 FP 指標即將出現的時候才開始下載動作,這個時間點是在 layout 完成以後。

圖中是以掘金為例,大家可以多試試別的網站,應該能發現是符合預期的。

那麼讀者可能會有個疑問,按照這個邏輯意思是說能用 img 的都用 img,因為background-image 不是馬上開始下載的?道理是這個道理,但是還是得分情況來說,如果圖片出現的位置不是首屏,用 background-image 也沒啥問題,當然給 img 用上懶載入也能解決問題。

那麼到底檔案的優先順序是如何的?

如果大家有使用過 Performance 測試網站效能的話,可以在 Network 那欄裡 hover 下載的資源,此時你能發現資源有優先順序的顯示。

入門 基礎知識點:瀏覽器到底是如何下載資源的

入門 基礎知識點:瀏覽器到底是如何下載資源的

入門 基礎知識點:瀏覽器到底是如何下載資源的

入門 基礎知識點:瀏覽器到底是如何下載資源的

入門 基礎知識點:瀏覽器到底是如何下載資源的

從圖中大家可以發現 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 時,就可以實現頻寬的分配,讓某些資源能更快地進行下載

入門 基礎知識點:瀏覽器到底是如何下載資源的

如圖所示(醜了點)。第一排的檔案開始一起下載,weight 相加為 20,那麼透過計算可得 CSS 檔案享有頻寬的一半,其他各佔有 1 / 4,JS 檔案得等 CSS 完成以後才開始。

那麼該如何設定這些東西呢?當然得服務端支援啦,一般都指 CDN 服務商了。

最後

查找了很多資料,如有遺漏,還請見諒。文中如果有誤,還望及時指出,感謝