網頁 head 標籤中的 JS 和 CSS,哪種文件放在前面,哪种放在後面比較好?


玉伯和克軍的文章主要說了資源載入順序的問題,我補充一下針對問題的回答。順序一般是:

1. 個別特殊JS,比如用於調試的基礎腳本(部署時未必有)、性能日誌之類,必須放在盡量最前的位置。

2. 外部樣式表(link[rel=stylesheet])

3. 本頁樣式(style)

4. 基礎庫,比如loader,各種shim/polyfill,jQuery之類的

注意,有些開發者從性能優化的角度傾向於加defer或者放到頁面的最底部。不過不是所有的腳本都能這樣做。比如html5-shim腳本必須在body之前載入。再如history api的兼容實現等都不應defer,因為你不能確保用戶在頁面ready之前沒有back/forward動作。再如jQuery,defer是可以,但也意味著你所有依賴jQuery的功能都需要defer,考慮到這些靜態文件通常都是有緩存的,所以不defer也未必不是一個可以接受的折衷。

5. 少量本頁script

以上。


跟著 @歐雷 的指引,在張克軍的博文中提到了另一篇深入探討的文章:http://lifesinger.wordpress.com/2012/02/03/performance-impact-of-js-css-loading-order/

------------------------ 由於 http://wordpress.com 這個網站「並不存在」,以下內容是通過 Pocket(原 ReadItLater)服務捏造而來,請看官自辨 -----------------------

JS 和 CSS 的位置對其他資源載入順序的影響

克軍做了一系列測試:js和css的順序關係,給出了現象和結論,但未給出原因。

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

  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 的下載時機都非常優先,和位置無關。

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

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

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

a,b – head里出現外聯js,無論如何放,css文件都不能和body里的請求並行

根據定律一和定律三,可以知道上面的結論不夠正確。比如:

& & &

& & & &

注意3:本文沒有考慮 defer, async 屬性的影響,這是另一個故事。

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


head 內的 JavaScript 需要執行結束才開始渲染 body,所以盡量不要將 JS 文件放在 head 內。可以選擇在 document complete 時,或者特定區塊後引入和執行 JavaScript。

而 CSS 應當寫在 head 中,以避免頁面元素由於樣式確實造成瞬間的白頁或者給用戶閃爍感。


@吳釗 說的是對的,以色列的開發人員加希尓在翻閱了現代瀏覽器內核源碼以後,寫了一文&<現代瀏覽器工作原理&>。瀏覽器中分主副解析引擎。head中引入的腳本可以直接柱塞主解析引擎的解析工作(比如某個瞬間我們發現網頁後面一片空白),如果這些腳本中有操作dom的函數,那麼這些函數不會執行,會被標識為延時狀態,等dom載入完後才會追趕執行。如果腳本中有可執行的函數,那麼dom的解析也會被柱塞,瀏覽器轉而要先去執行腳本。腳本執行完畢後,dom解析才繼續。

為了避免head引入的腳本柱塞主解析引擎對dom的解析工作,更快的載入dom並渲染出來,一般的原則是,樣式放在前面,腳本放在最後面。遵從先解析再渲染再執行script這個順序。yahoo21條中也有提及。


參考:http://blog.csdn.net/uohzoaix/article/details/7299054

http://www.huilinwang.com/blog/post/87.html.html


不同意因為js腳本會阻塞dom構建的原因,而將js腳本放在末尾。

Edit fiddle - JSFiddle

就算放在末尾了,也一樣會阻塞dom的構建。


推薦閱讀:

2016年前端技術將會呈現怎樣的局勢?全棧工程師是不是前端的一個趨勢?
web移動前端有哪些優化方案?
如何分析頁面性能?
公司官網的圖片用什麼格式比較好?

TAG:前端開發 | CSS | JavaScript | HTML5 | 前端性能優化 |