跳到主要內容
黯羽輕揚每天積累一點點

無阻塞載入腳本的最佳方案

免費2015-11-27#JS#Solution#script的defer#defer属性#JavaScript无阻塞加载脚本#js并行加载脚本

無阻塞載入外部腳本,加快頁面渲染速度

##最佳方案

沒有獨立的最佳方案,真正的最佳方案取決於需求,選擇最佳腳本下載技術的決策樹如下:

[caption id="attachment_860" align="alignnone" width="300"]選擇最佳腳本載入技術的決策樹 選擇最佳腳本載入技術的決策樹[/caption]

在決策樹裡有 6 種可能的結果:

  • 不同網域、無序

XHR Eval、XHR 注入和 Script in Iframe 技術在這些情況下無法使用,因為主頁面的網域與腳本的網域不同。我們不應該使用 Script Defer 技術,因其迫使腳本按順序載入,相反,如果腳本能一到達就執行的話會讓頁面載入更快一些。對於這種情況,Script DOM Element 技術是最佳方案,但它會導致在 Firefox 中載入時保持順序,雖然我們並不希望這樣。注意這兩種技術都觸發忙指示器(狀態列、進度條、圖示、游標),但我們沒有辦法避免這個問題。

包含 JavaScript 廣告和控制項的網頁是符合這種情況的實例。廣告和控制項的腳本所在的網域往往和主頁面不同,但是它們之間沒有任何依賴關係,所以載入順序無關緊要。

  • 不同網域、保持順序

和前面一樣,因為主頁面的網域與腳本不同,XHR Eval、XHR 注入和 Script in Iframe 技術行不通。為了確保載入順序,我們應該在 Internet Explorer 中使用 Script Defer 技術,而在 Firefox 中使用 Script DOM Element 技術。注意這兩種技術都觸發忙指示器。

一個符合這種情況的實例是從不用的伺服器下載多個存在相依關係的 JavaScript 檔案的頁面。

  • 同網域、無序、無忙指示器

XHR Eval 和 XHR 注入是唯一不觸發忙指示器的兩種技術。這兩種 XHR 技術,我更推薦 XHR 注入,因為使用該技術時腳本無需重構。

可以應用於希望在背景下載 JavaScript 檔案的網頁

  • 同網域、無序、有忙指示器

XHR Eval、XHR 注入和 Script in Iframe 是唯一跨 Internet Explorer 和 Firefox 而不保持載入順序的技術。Script in Iframe 技術看起來似乎是最佳選擇,因為它觸發忙指示器,而且只是稍微增加了一些頁面大小。但我更傾向於 XHR 注入,因為使用該技術時腳本無需重構就能使用,而且它同時是其他決策樹分支的選擇。我們需要額外的 JavaScript 來啟動忙指示器:當 XHR 發出時啟動狀態列和游標,XHR 返回時恢復,我們稱之為 Managed XHR Injection

  • 同網域、保持順序、無忙指示器

XHR Eval 和 XHR 注入是兩個不觸發忙指示器的技術。這兩種 XHR 技術中我更傾向於 XHR 注入,因為使用該技術時腳本無需重構。為了保持載入順序,需要另一種類型的 Managed XHR Injection。在這種情況下,如有必要,可以把 XHR 回應塞進佇列裡,按順序執行,延遲載入的腳本需要在它之前的所有腳本下載並執行完畢後才開始執行,

有多個存在內部相依的腳本在背景下載的頁面符合這種情況

  • 同網域、保持順序、有忙指示器

Internet Explorer 中的 Script Defer 技術和 Firefox 中的 Script DOM Element 技術是首選方案。Managed XHR Injection 和 Managed XHR Eval 技術也是可行的。但是它們會給主頁面增加額外的程式碼,而且實現它們更複雜一些。

P.S. 以上內容摘自參考資料

##XHR Eval

xhr 獲取腳本 str,然後 eval(str) 執行

優點:無阻塞(不會阻塞其他資源的下載)

缺點:同源策略(Same Origin Policy)限制,外部腳本必須與正在執行的腳本同網域(協定、連接埠號碼、功能變數名稱)。此外,外部腳本可能需要重構

##XHR 注入

xhr 獲取腳本 str,然後把 str 塞進 script 元素,再插入 DOM 樹執行

優點:無阻塞

缺點:SOP 限制

##Script in Iframe

頁面中的 iframe 和其他資源是平行載入的,可以利用這個特點來實現無阻塞載入腳本:

<!-- 在主页面中内包含iframe,jsWrapper.html应该与主页面同域 -->
<iframe src="jsWrapper.html" frameborder="0" width="0" height="0" id="myIframe"></iframe>

//---js通信
// 主页面 -> iframe
var winIframe = window.frames['myIframe'].contentWindow;
winIframe.fun();    // winFrame是iframe中的window对象
// iframe -> 主页面
var winMain = window.parent;
winMain.fun();      // winMain是主页面中的window对象

注意srcx.html 而不是 x.js,因為 iframe 認為返回的是 html 文件,所以應該把腳本用 html 包裝成 inline script

優點:無阻塞

缺點:SOP 限制,且外部腳本需要重構

##Script DOM Element

動態建立 script 元素設置 src 並插入 DOM 樹

優點:無阻塞,允許跨域,外部腳本無需重構,能夠保證腳本執行順序

缺點:IE 下不能保證腳本執行順序

##Script Defer

IE 支援 script 標籤的 defer 屬性,允許其他資源平行下載

優點:容易(給 script 標籤添一個屬性就行),而且能夠保證腳本執行順序

缺點:某些瀏覽器(比如低版本 FF)可能不支援該屬性,但 html5 標準 已經確定了 deferasync 的地位,而且新增了 onload 回呼,目前相容性問題不嚴重,更多資訊請查看 HTML5 <script>元素async,defer非同步載入

##document.write Script Tag

document.writescript 標籤寫入頁面

優點:在 IE 用 document.write 寫入的多個腳本可以平行載入

缺點:只有 IE 無阻塞,而且在載入這些腳本時,其他資源(圖片,DOM)都會被阻塞

###參考資料

  • 《高效能網站建設進階指南》

評論

暫無評論,快來發表你的看法吧

提交評論