2012-05-21 96 views
4

這是從HTML5 Boilerplate的index.html,只是</body>標記之前:運行腳本標記是否阻止其他腳本標記下載?

<!-- JavaScript at the bottom for fast page loading: http://developer.yahoo.com/performance/rules.html#js_bottom --> 

<!-- Grab Google CDN's jQuery, with a protocol relative URL; fall back to local if offline --> 
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js"></script> 
<script>window.jQuery || document.write('<script src="js/vendor/jquery-1.7.2.min.js"><\/script>')</script> 

<!-- scripts concatenated and minified via build script --> 
<script src="js/plugins.js"></script> 
<script src="js/main.js"></script> 
<!-- end scripts --> 

<!-- Asynchronous Google Analytics snippet. Change UA-XXXXX-X to be your site's ID. 
    mathiasbynens.be/notes/async-analytics-snippet --> 
<script> 
    var _gaq=[['_setAccount','UA-XXXXX-X'],['_trackPageview']]; 
    (function(d,t){var g=d.createElement(t),s=d.getElementsByTagName(t)[0]; 
    g.src=('https:'==location.protocol?'//ssl':'//www')+'.google-analytics.com/ga.js'; 
    s.parentNode.insertBefore(g,s)}(document,'script')); 
</script> 

我知道腳本標記可以阻止並行下載,這是爲什麼it's recommended to put them at the bottom

我的問題:是否真的瀏覽器等待jQuery來完全下載並執行它甚至開始下載plugins.js然後script.js過嗎?

抑或是向前看,儘快開始下載的所有腳本地(並行),只是延緩每個腳本的執行直到前一個已經執行完畢?

回答

8

我的問題:是否真的瀏覽器等待jQuery來完全下載並執行它甚至開始下載plugins.js然後script.js過嗎?

它可能會也可能不會,但可能不會;瀏覽器嘗試(限制範圍內)並行下載,以加快頁面加載速度。

抑或是向前看,儘快啓動所有的腳本下載越好(並行),只是延緩執行每個腳本直到前一個已經執行完畢?

權,因爲這部分是required by the specification(在asyncdefer屬性由於缺少)。正如您的示例所示,它甚至不一定會確定腳本在腳本運行之前的運行順序,因爲該腳本可能會插入另一個腳本。但它可以下載並準備好它們。

+0

這是否意味着像JavaScript異步加載技術這樣的最佳實踐在當今較新的瀏覽器中不那麼重要?他們是否只記得文檔中出現的外部腳本鏈接在並行下載後執行它們的順序?這似乎是因爲如果我看看Chrome開發者工具/資源面板,大量的js文件同時開始下載並且不會像書籍中的屏幕截圖一樣被阻止(例如,「更快的網站」)顯示爲例。 – malthoff

+0

@malthoff:*「他們是否記得在文檔中出現的外部腳本鏈接在並行下載後執行它們的順序?」*正確。如果你有(說)五個腳本,但是它們加載其中兩個的順序並不重要,你可以標記那些'async',在這種情況下(在現代瀏覽器上),只要他們'重新下載,不管順序如何。 –

+0

「但它可以下載並準備好它們。」但事實上,瀏覽器是這樣做的嗎? – callum

1

HTML5規範表示:

如果既沒有屬性[即async and defer]存在,那麼在用戶代理繼續解析 頁面之前,腳本被取出並立即執行。

如果頁面無法解析,那麼用戶代理無法知道哪些後續的資源獲取需要,因此嚴格遵循規則的瀏覽器不應該能夠直到第一個已實際執行來獲取更多的資源。

爲了說明爲什麼這是有道理的,假設第一個腳本包含

document.write("<!--"); 

沒有匹配的註釋關閉,則後面的標記,該腳本將成爲註釋的一部分,直到下一個-->就是一切遇到。這可能會導致跳過一個或多個資源引用。

1

我發現這個細節更合適這個問題的答案,複製下面的內容從http://www.html5rocks.com/en/tutorials/speed/script-loading/提到它的更多細節。

< SCRIPT SRC = " //other-domain.com/1.js " > < /腳本>

< SCRIPT SRC = " 2.js " > < /腳本>

稀釋,幸福簡單。在這裏,瀏覽器將同時下載兩個腳本並儘快執行它們,以維護它們的順序。直到「1.js」執行完成(或不執行),「2.js」纔會執行,「1.js」將不會執行,直到前面的腳本或樣式表執行完成等等。不幸的是,瀏覽器阻止了進一步的頁面渲染,而這一切正在發生。這是由於「網絡第一時代」的DOM API允許字符串被附加到解析器正在咀嚼的內容上,如document.write。較新的瀏覽器將繼續在後臺掃描或解析文檔,並觸發它可能需要的外部內容(js,圖像,css等)的下載,但渲染仍然被阻止。

這就是爲什麼性能世界的偉大和好處建議將腳本元素放在文檔的末尾,因爲它會盡可能地阻塞內容。不幸的是,它意味着你的腳本在下載你所有的HTML之前不會被瀏覽器看到,並且到那時它開始下載其他內容,比如CSS,圖像和iframe。現代瀏覽器足夠聰明,可以優先考慮JavaScript和圖像,但我們可以做得更好。