你瞭解JavaScript非阻塞載入指令碼嗎

來源:互聯網
上載者:User

As more and more sites evolve into “Web 2.0″ apps, the amount of JavaScript increases. This is a performance concern because scripts have a negative impact on page performance. Mainstream browsers (i.e., IE 6 and 7) block in two ways:

  • Resources in the page are blocked from downloading if they are below the script.
  • Elements are blocked from rendering if they are below the script.

隨著越來越多的網站涉及“Web 2.0”應用,JavaScript指令碼的數量也急劇增加。這是令人憂慮的,因為指令碼對頁面效能有負面影響。主流的瀏覽器(例如IE 6 、7)會以下面2種方式發生阻塞:

  • 如果資源位於指令碼的下方,那麼他們會被阻塞下載。
  • 如果元素位於指令碼的下方,那麼他們會被阻塞渲染展示。

The Scripts Block Downloads example demonstrates this. It contains two external scripts followed by an image, a stylesheet, and an iframe. The HTTP waterfall chart from loading this example in IE7 shows that the first script blocks all downloads, then the second script blocks all downloads, and finally the image, stylesheet, and iframe all download in parallel. Watching the page render, you’ll notice that the paragraph of text above the script renders immediately. However, the rest of the text in the HTML document is blocked from rendering until all the scripts are done loading.

這個指令碼阻塞下載的例子(Scripts Block Downloads example) 展示了上面的情況。它包括2個外部指令碼,後面是1個圖片、1個樣式表和1個iframe。使用IE7載入這個例子的HTTP瀑布圖顯示了第一個指令碼阻塞了所有的下載,隨後第2個指令碼阻塞了所有的下載,最後圖片樣式表和iframe並行載入。觀察頁面的渲染情況,你會發現指令碼上方的那段文字會馬上渲染。然而,HTML 文檔其它部分的文字會被阻塞,直到所有的指令碼被下載完畢。

在 IE6 7, Firefox 2 3.0, Safari 3, Chrome 1, Opera 指令碼均會阻塞下載

Browsers are single threaded, so it’s understandable that while a script is executing the browser is unable to start other downloads. But there’s no reason that while the script is downloading the browser can’t start downloading other resources. And that’s exactly what newer browsers, including Internet Explorer 8, Safari 4, and Chrome 2, have done. The HTTP waterfall chart for the Scripts Block Downloads example in IE8 shows the scripts do indeed download in parallel, and the stylesheet is included in that parallel download. But the image and iframe are still blocked. Safari 4 and Chrome 2 behave in a similar way. Parallel downloading improves, but is still not as much as it could be.

如果瀏覽器是單線程的,那麼當一個指令碼在執行時,瀏覽器不能下載其它資源是可以理解的。但是沒有理由解釋當指令碼下載時瀏覽器不能下載其它資源。下載指令碼的同時並行下載其它資源是所有最新瀏覽器的已經實現了的功能,包括Internet Explorer 8, Safari 4, Chrome 2。在IE8中開啟指令碼阻塞下載的例子(Scripts Block Downloads example)的HTTP瀑布圖展示了指令碼確實是並行下載的,樣式表也是並行下載的,然而圖片和iframe仍舊被阻塞了。Safari 4 和 Chrome 2 的行為也很類似。並行下載改善了一部分,但還沒有達到它能達到的最好的效果。

IE8, Safari 4, Chrome 2下,指令碼仍舊是阻塞的

Fortunately, there are ways to get scripts to download without blocking any other resources in the page, even in older browsers. Unfortunately, it’s up to the web developer to do the heavy lifting.

幸運的是,即使在更老的瀏覽器中,也有使指令碼不阻塞其它頁面資源的辦法。不幸的是,這取決於web開發人員是否願意承擔這些繁重的工作。

There are six main techniques for downloading scripts without blocking:

  • XHR Eval – Download the script via XHR and eval() the responseText.
  • XHR Injection – Download the script via XHR and inject it into the page by creating a script element and setting its text property to the responseText.
  • Script in Iframe – Wrap your script in an HTML page and download it as an iframe.
  • Script DOM Element – Create a script element and set its src property to the script’s URL.
  • Script Defer – Add the script tag’s defer attribute. This used to only work in IE, but is now in Firefox 3.1.
  • document.write Script Tag – Write the <script src=""> HTML into the page using document.write. This only loads script without blocking in IE.

下面有6種非阻塞式載入指令碼的技術:

  • XHR Eval - 通過XHR下載指令碼,通過eval()執行。
  • XHR Injection - 通過XHR下載指令碼,通過建立一個script的DOM元素注入頁面,並且設定text屬性。
  • Script in Iframe - 在一個HTML頁面內包含指令碼並通過iframe載入。
  • Script DOM Element - 建立一個script的DOM元素,並且設定src屬性為指令碼的url。
  • Script Defer - 增加指令碼的defer屬性。曾經僅在IE中可用,現在Firefox 3.1. 中也可以了。
  • document.write Script Tag - 在HTML頁面內使用document.write <script src="">。僅在IE有效。

You can see an example of each technique using Cuzillion. It turns out that these techniques have several important differences, as shown in the following table. Most of them provide parallel downloads, although Script Defer and document.write Script Tag are mixed. Some of the techniques can’t be used on cross-site scripts, and some require slight modifications to your existing scripts to get them to work. An area of differentiation that’s not widely discussed is whether the technique triggers the browser’s busy indicators (status bar, progress bar, tab icon, and cursor). If you’re loading multiple scripts that depend on each other, you’ll need a technique that preserves execution order.

在Cuzillion你可以看到每個技術的範例。事實證明這些技術有重要的區別,見下面表格。它們大部分提供並行下載,有些技術不能被使用在跨網域名稱的指令碼上,有些必須在你已有的指令碼基礎上簡單的修改,還有一個未被廣泛討論的是否觸發瀏覽器的繁忙指示標記區別(狀態列,進度條,標籤表徵圖和游標)。如果你需要載入多個相互依存的指令碼,你還需要一個維護執行順序的技術。

技術名稱 支援並行下載 支援跨網域名稱 不需修改指令碼 是否有繁忙指示 保障執行順序 大小(位元組)
XHR Eval IE, FF, Saf, Chr, Op no no Saf, Chr - ~500
XHR Injection IE, FF, Saf, Chr, Op no yes Saf, Chr - ~500
Script in Iframe IE, FF, Saf, Chr, Op no no IE, FF, Saf, Chr - ~50
Script DOM Element IE, FF, Saf, Chr, Op yes yes FF, Saf, Chr FF, Op ~200
Script Defer IE, Saf4, Chr2, FF3.1 yes yes IE, FF, Saf, Chr, Op IE, FF, Saf, Chr, Op ~50
document.write Script Tag IE, Saf4, Chr2, Op yes yes IE, FF, Saf, Chr, Op IE, FF, Saf, Chr, Op ~100

The question is: Which is the best technique? The optimal technique depends on your situation. This decision tree should be used as a guide. It’s not as complex as it looks. Only three variables determine the outcome: is the script on the same domain as the main page, is it necessary to preserve execution order, and should the busy indicators be triggered.

問題是:哪個是最好的技術?最佳的技術取決於您的具體情況。下面這個決策樹可以作為一個指導。它看起來複雜,其實並不是。只有3個參數就決定了輸出結果:指令碼是否在首頁面的同一個網域名稱之下,是否需要保障執行順序,是否需要觸發繁忙指示標記。

Ideally, the logic in this decision tree would be encapsulated in popular HTML templating languages (PHP, Python, Perl, etc.) so that the web developer could just call a function and be assured that their script gets loaded using the optimal technique.

最理想的是,這個決策樹的邏輯將體現在流行的HTML範本語言中(PHP, Python, Perl, 等),因此WEB開發人員可以簡單的調用一個函數,就能保證他們的指令碼使用最佳的技術來載入指令碼。

In many situations, the Script DOM Element is a good choice. It works in all browsers, doesn’t have any cross-site scripting restrictions, is fairly simple to implement, and is well understood. The one catch is that it doesn’t preserve execution order across all browsers. If you have multiple scripts that depend on each other, you’ll need to concatenate them or use a different technique. If you have an inline script that depends on the external script, you’ll need to synchronize them. I call this “coupling” and present several ways to do this in Coupling Asynchronous Scripts.

很多情況下,使用 Script DOM Element是一個不錯的選擇。它可以在所有瀏覽器下工作,沒有任何跨域限制,代碼上很容易實現,很容易被理解,唯一不足的是並不是在所有瀏覽器下均能保持正確的執行順序。如果你有多個指令碼並且相互依賴,你需要合并他們或使用其它技術。如果你在頁面內有依賴於外部指令碼的內聯指令碼,你必須對他們實現同步化,我將這個方法稱為“coupling” 並在耦合非同步指令碼中提出一些可以做到這一點的方法。

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.