天天看點

js并行加載,順序執行js并行加載,順序執行

js并行加載,順序執行

<script>運作腳本或加載外部檔案時,會阻塞頁面渲染,阻塞其他資源的加載。如果頁面中需要加載多個js檔案,在古老浏覽器中性能會比較糟糕。 是以有了最原始的優化原則:把腳本放在底部。

如何實作js非阻塞、并行加載,甚至能保持執行順序呢?各浏覽器表現如何?站在巨人的肩膀上,Kyle Simpson、Nicholas C. Zakas和Steve Souders對此有過總結和方案。

背景

1. Script DOM Element。 動态插入<script>,不會阻塞,但無法保持執行順序。但唯有Firefox可以保持執行順序,但也差點在Firefox 4 nightly的版本中去掉這個特性。

2. HTML5 async 非阻塞,加載完後立即執行,不保證順序。這個屬性不管有沒有值、值為true或false,都是等同的效果(由于Kyle的推進,不能保證執行順序與其值無關了)。

Google Analytics的新版嵌入代碼就結合使用了上面兩個方案,如:

1 2 3 4 5 6 7 8

var

ga = document.createElement(

'script'

);

ga.type =

'text/javascript'

;

ga.async =

true

;

ga.src = (

'https:'

== document.location.protocol ?

'https://ssl'

:

'http://www'

)

+

'.google-analytics.com/ga.js'

;

var

s = document.getElementsByTagName(

'script'

)[0];

s.parentNode.insertBefore(ga, s);

3. IE partsandspares.co.za defer屬性。不阻塞,可以保證順序,在DOM加載完成後執行(在DOMContentLoaded之前)。

4. <script>的type屬性設為”script/cache” 非标準的type屬性,使js檔案隻會被加載而不會執行。需要執行時,建立一個type屬性為”text/javascript”的正常<script>元素,src設為前面已經加載的js位址即可,執行順序開發者可控(執行時機也完全可控)。類似的方式也有通過<img>來做預加載的。

5. document.write。文檔流關閉後執行會清空整個頁面。

6. XHR 并行加載,執行順序可控,但有同域限制。

基本需求

Steve Souders 和 Nicholas C. Zakas 一起總結了下,認為js加載方案必須解決以下問題:

  1. 支援特性檢測
  2. 不會重複加載
  3. 支援并行加載

開發者的美好願望

Nicholas C. Zakas 幾經周折,有了以下的提案,分離js的加載和執行,友善開發者自由控制js的執行時間。

1 2 3 4 5 6 7 8 9 10 11 12 13

var

script = document.createElement(

"script"

);

// 此屬性僅可由js動态寫入,在HTML标簽中直接寫入無效

script.preload =

true

;

// src指派後,立即觸發加載(僅加載,不會執行js内容)

script.src =

"foo.js"

;

// onpreload是需要新支援的事件,加載完成後觸發此事件

script.onpreload =

function

(){

// 在需要時,将加載的js插入到DOM中,即可運作生效

document.body.appendChild(script);

};

基于特性檢測feature detection(差別于特性推測feature inference)

var isPreloadSupported = (typeof script.preload == “boolean”);

這一特性隻有在Javascript中動态指派時生效,直接寫到HTML标簽上時是無效的。

但這隻是一個提案,開發者們的美好願望,而非被浏覽器支援的标準。目前這一提案已在LABjs中支援,Zakas本人也在積極推進此提案的标準化。

而Kyle在推進另外一種方式,即要求對含有屬性async=false的<script>保持執行順序。如果async=true,則一旦加載完則會馬上執行腳本,不會嚴格保持順序。預設地,頁面中的<script>的async屬性為false,即保持執行順序;js建立的<script>的async屬性為true,即加載完立即執行,不保證順序。

為了支援特性檢測,一個由js建立的<script>标簽預設具有async=true的屬性。

Kyle的這一提案已被HTML5小組接受放入草案,在Firefox 4 nightly版本中的也已實作。

Firefox 4為了更向HTML5标準看齊,一度在開發者版本中去掉了對動态建立<script>來加載js檔案的執行順序支援:

<script> elements created using document.createElement() and inserted into a document now behave according to the HTML5 specification by default. Scripts with the src attribute execute as soon as available (without maintaining ordering) and scripts without the src attribute execute synchronously.

為此,Kyle向WebKit開發團隊抗議,提了一個bug,最終得到了如他所願的支援:

To make script-inserted scripts that have the src attribute execute in the insertion order, set .async=false on them.

Zakas很欣賞Kyle的方案,Kyle在LABjs中也支援了Zakas的提議,各浏覽器們也這麼和諧就好了。

轉自:http://www.impng.com/web-dev/parallel-download-ordered-execute.html

繼續閱讀