JS 和 CSS 的位置對其餘資源加載順序的影響

JS 和 CSS 在頁面中的位置,會影響其餘資源(指 img 等非 js 和 css 資源)的加載順序,究其緣由,有三個值得注意的點:php

  1. JS 有可能會修改 DOM. 典型的,可能會有 document.write. 這意味着,在當前 JS 加載和執行完成前,後續全部資源的下載有多是不必的。這是 JS 阻塞後續資源下載的根本緣由。
  2. JS 的執行有可能依賴最新樣式。好比,可能會有 var width = $('#id').width(). 這意味着,JS 代碼在執行前,瀏覽器必須保證在此 JS 以前的全部 css(不管外鏈仍是內嵌)都已下載和解析完成。這是 CSS 阻塞後續 JS 執行的根本緣由。
  3. 現代瀏覽器很聰明,會進行 prefetch 優化。性能是如此重要,現代瀏覽器在競爭中,在 UI update 線程以外,還會開啓另外一個線程,對後續 JS 和 CSS 提早下載(注意,僅提早下載,並不執行)。有了 prefetch 優化,這意味着,在不存在任何阻塞的狀況下,理論上 JS 和 CSS 的下載時機都很是優先,和位置無關。

以上三點可簡述爲三條基本定律:css

  • 定律一:資源是否下載依賴 JS 執行結果。
  • 定律二:JS 執行依賴 CSS 最新渲染。
  • 定律三:現代瀏覽器存在 prefetch 優化。

有了這三條定律,再來看克軍的測試,就很清晰了:css3

a,b – head裏出現外聯js,不管如何放,css文件都不能和body裏的請求並行瀏覽器

根據定律一和定律三,能夠知道上面的結論不夠正確。好比:async

1 <head>
2 <link rel="stylesheet" href="mock.php?css1&sleep=2">
3 <script src="mock.php?js&sleep=3"></script>
4 <link rel="stylesheet" href="mock.php?css2&sleep=4">
5 </head>
6 <body>
7 <link rel="stylesheet" href="mock.php?css3&sleep=5">
8 <img src="test.gif">
9 </body>

 

在 Chrome 下的瀑布圖是:性能

 

黃色條是 js 的,能夠看出 img 的延時下載是由定律一決定的。學習

定律三則決定了全部 js/css 都是並行開始下載的。在 Firefox 10 下,prefetch 很是強悍,對 img 也會預加載,瀑布圖以下:測試

調整一下 sleep 時間,還能夠觀察到定律二的威力:fetch

1 <head>
2 <link rel="stylesheet" href="mock.php?css1&sleep=3"> <!-- 修改 sleep 值,使其大於 js 的 -->
3 <script src="mock.php?js&sleep=2"></script>
4 <link rel="stylesheet" href="mock.php?css2&sleep=4">
5 </head>
6 <body>
7 <link rel="stylesheet" href="mock.php?css3&sleep=5">
8 <img src="test.gif">
9 </body>

 

瀑布圖馬上發生了變化:優化

由於定律一,決定 img 的下載在 js 執行後。又由於定律二,決定 js 的執行在第一個 css 後。因而最後在瀑布圖上體現出來,就是 img 的下載在第一個 css 後。

再來看克軍的第二個結論:

c – head裏的內聯js只要在全部外聯css前面,css文件能夠和body裏的請求並行(圖2)
d – head裏的內聯js只要在任一外聯css後面,css文件就不能和body裏的請求並行(圖1)

這個是定律二的威力。結論 c 是正確的,由於沒有 css 會影響 js 的執行。結論 d 則不夠正確。img 等其餘資源,會在 js 前面的 css 下載完成後,以及 js 執行後,馬上開始下載。與頭部中,js 位置以後的 css 不要緊。

克軍的其餘結論都是對的,很少說。

注意1:Firefox 10 的 prefetch 有點奇怪,有時會對 img 進行 prefetch,有時則不會。有興趣的能夠進一步尋找規律。
注意2:上面的三個定律,是黑盒猜想,有興趣的能夠去閱讀瀏覽器的源碼,應該能找到更深層次的緣由。
注意3:本文沒有考慮 defer, async 屬性的影響,這是另外一個故事。

瀏覽器在迅速發展,不少總結,特別是書籍上的,很難與時俱進。你們應該像克軍學習,多測試,多發現,這樣得來的知識,纔不會過期。這篇博客的總結,也確定在將來甚至就在如今,已經存在錯誤。這些都無所謂,關鍵是要懂得測試的方法和分析的思路,有了「漁」,才能更好地探求和擁有「魚」

相關文章
相關標籤/搜索