[轉]預先載入資源研究

來源:互聯網
上載者:User

標籤:

原文:http://www.otakustay.com/prefetch-resource/

什麼是預先載入

所謂預先載入,就是通過一定的編程方法,使瀏覽器在空間的時候,在後台通過HTTP請求訪問某些資源。當使用者在一段時間後真正使用這些資源的時候,相比一個完整的(返回200)的請求,可以更快地獲得這些資源(返回304或者直接命中瀏覽器緩衝)。

預先載入在部分情況下有著十分重要的意義,特別是當確定某些資源使用者在短時間內會使用,如分頁列表的上一頁和下一頁、以及一些常用的LOGO之類的圖片等。

預先載入資源可能的方式

預先載入的原理就是想辦法發送一個HTTP請求,對響應的緩衝等都由瀏覽器完成,因此一切有可能讀取遠端資源的方案都可以成為預先載入資源的方案,大致有以下幾類:

常規方式
  • 使用script標籤:<script type="other/prefetch" src="some.res"></script>
  • 使用img標籤:<img src="some.res" />
  • 使用iframe標籤:<iframe src="some.res"></iframe>
  • 使用XMLHttpRequest載入:$.get(‘some.res‘);
  • 使用Flash進行載入:需要編寫特定的Flash
非常規方式
  • 使用背景圖片:<div style="background-image: url(some.res);"></div>
  • 使用object或embed標籤:<object type="other/prefetch" src="some.res"></object>
  • 使用link標籤並修改media:<link rel="stylesheet" href="some.res" media="prefetch" />
  • 在CSS中做import:@import "some.res"
新一代方法
  • 使用Link Prefetch:<link rel="prefetch" href="some.res" />
  • 使用WebWorker:var worker = new Worker(‘some.res‘);
  • 使用@font-face:@font-face { font-family: prefetch; src: url(some.res); }

方法有很多,也可能會有更多,具體的使用方式就不詳細說明了,具體需要注意的細節會在後文詳細描述。

預先載入資源方式的評估指標

每一種方式或多或少都有其長處和缺點,本次主要按以下幾個維度進行評估:

[A]瀏覽器安全色性
主要考察包括IE6-8、Firefox3.5+、Chrome7+、Opera9+以及Safari4+的相容性。
[B]資源位置的覆蓋性
主要考察是否有跨域政策的限制,是否能讀取第三方的資源。
[C]引入第三方資源的安全性
主要考察是否會對載入的資源進行解析和執行,是否可能產生如XSS等安全問題。
[D]引入資源類型的覆蓋性
主要考察是否可以引入不同類型的資源,包括text、image、script、html等。
[E]是否可以確定何時完成預先載入
由於預先載入資源用時的不確定性,有可能導致使用者在資源未載入完成時產生行為導致載入請求被中斷。因此需要考察資源的載入完成是否可控,主要考察是否有load、error、readystatechange等事件。
[F]積累的標籤的清理可行性
如果預先載入資源的方法會引入多餘的標籤,如link、script等,需要考察在資源載入過程中,將對應的標籤刪除是否會導致請求中斷。
評估中出現的問題

隨著不斷深入,各種方案的缺陷也被一點點挖掘,以下是一些不太容易注意到的奇怪的問題。

script標籤

在Firefox下,當script標籤的type屬性是Firefox無法識別的指令碼類型時,Firefox不會發送任何請求,基本上除了type="text/javascript"以外,Firefox都不予理睬。

img標籤以及background-image

在Firefox下,當img標籤或者background-image樣式請求的內容返回的Content-Type不是image大類時,其響應體(Response Body)只會被接收1個包,其後的內容全部丟棄。

Flash

對於跨域的請求,Flash會先讀取對方伺服器上的策略xml檔案,如策略檔案允許跨域,則會進行載入。

object或embed標籤

在Firefox下,無論元素是否隱藏,都會提示要求安裝外掛程式,當然這外掛程式是找不到的。

在Chrome下,如果元素被隱藏,則不發起請求;元素未隱藏則提示安裝外掛程式。

在下載完外掛程式前,所有瀏覽器都不會發起請求。

但如果object標籤的type使用text/plain則不存在安裝外掛程式的問題,不過悲劇的是在IE下不會發出請求,而在Firefox和Chrome下會解析執行HTML資源

需要注意的是,object元素有其特殊性,建立一個object元素的代價遠遠大於其他元素。

link標籤

在IE下有load事件,Opera中可以定時查看readystate以確定是否完成了請求,在其他瀏覽器中則不存在。

Link Prefetch

現階段僅Firefox給予了支援,該功能在HTML5草案中,非常值得期待。

WebWorker

使用WebWorker載入的指令檔會立刻被解析和執行,雖然在worker中的global對象是帶有一定限制的,但依舊無法完全阻止第三方指令碼注入有害的代碼。

@font-face

@font-face僅在樣式表中定義是不會發起請求的,必須建立一個元素,將其font-family設為該font-face,並且該元素必須被添加到DOM樹中才會產生請求。

評估表格及基本判斷

表格從前文所述的A-F共6個方面來考察各種預先載入資源的方式,以期較為直觀地去評價各種方式的優劣。

[A]瀏覽器安全色性    [B]是否跨域    [C]安全性    [D]資源類型    [E]是否有onload    [F]是否可以刪除標籤
*:只實測了DOM元素被刪除後的效果,因無法控制GC,未測元素對象被GC的情況。
  [A] [B] [C] [D] [E] [F]*
script 1 1 1 0 1 1
img 0 1 1 0 1 1
iframe 1 1 0 1 1 1
XMLHttpRequest 1 0 1 1 1 1
Flash 1 0 1 1 1 1
背景圖片 0 1 1 0 0 1
object/embed 0 1 0 0 1 1
link + media 1 1 1 1 0 1
@import 1 1 1 1 0 1
Link Prefetch 0 1 1 1 0 1
WebWorker 0 1 0 1 0 1
@font-face 0 1 1 1 0 1

從表格展現的資料來看,link+media的方式以及css @import方式都比較優秀,唯一的遺憾是無法獲得其是否載入完成,因此需要網站自身通過研究使用者的行為,保證使用者2次操作的間隔足夠完成資源的載入。

其他考慮
  • Link Prefetch作為HTML5草案中的標準,且瀏覽器底層層級支援,因此瀏覽器可以在頻寬空餘地時候才進行預先載入,使用者也可以通過一定的方式關閉該功能,各方面都有不俗的表現,如果可以推廣到主流瀏覽器,應該是作為最值得推薦的方案。
  • @import需要伺服器端輔助,將需要載入的資源打包成一個css格式的檔案,檔案中包含若干個@import聲明,但是無論如何,瀏覽器會需要多一個請求用於載入這個動態產生的css檔案。
  • link+media的方式中,可以通過修改link的href屬性,使用一個link載入多個資源,不會因為標籤過多導致DOM結構的臃腫以至於影響效能。
  • 在IE下,使用link+media的方式,無論下載來的內容是否被解析,IE會對頁面進行一次redraw,這一次redraw的效能損失非常小,大致只是進入了redraw方法,但並沒有真正地重新進行布局。
  • object標籤必須與DOM樹相連才會載入資源,使用object標籤時,在非IE瀏覽器下,可以將object標籤的寬和高均設為0,但IE不行。在IE中可以將寬高均設為1,並使用visibility: hidden; position: absolute; top: 0; z-index: -1000;的樣式來將其隱藏。當然既然IE不會發起請求,就怎麼設也沒意義了……
結論?

根據使用情境的不同,不會有一種萬能的最佳解決方案,但大致可以總結如下:

  • 載入同域資源,使用XMLHttpRequest即可。
  • 載入第三方可信任的資源,如同公司內不同系統,可以使用iframe載入非HTML資源。
  • 載入圖片資源,使用img是最好的方式,但需要注意在請求過程中img不能被GC回收。
  • 對於第三方的不可信任型資源,考慮使用link+media的方式載入,但無法確定載入完成的時間點。
  • 如果可以判斷瀏覽器,針對Firefox使用Link Prefetch,針對IE使用img標籤,其他瀏覽器使用script標籤算是一種較為完美的解決方案。
  • 從未來看,Link Prefetch必將是大勢所趨,大家給WHATWG提意見,讓他加上onload吧。
參考資料
  • Mozilla Developer Center的Link Prefetching
  • Wikipedia上的Link Prefetching
  • 藉助HTML5 Web Worker 解決資源預先載入的一些頑疾
  • Franky的HTML5 Web Worker

[轉]預先載入資源研究

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在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.