?
什么是預加載
所謂預加載,就是通過一定的編程方法,使瀏覽器在空間的時候,在后臺通過HTTP請求訪問某些資源。當用戶在一段時間后真正使用這些資源的時候,相比一個完整的(返回200)的請求,可以更快地獲得這些資源(返回304或者直接命中瀏覽器緩存)。
預加載在部分情況下有著十分重要的意義,特別是當確定某些資源用戶在短時間內(nèi)會使用,如分頁列表的上一頁和下一頁、以及一些常用的LOGO之類的圖片等。
預加載資源可能的方式
預加載的原理就是想辦法發(fā)送一個HTTP請求,對響應的緩存等都由瀏覽器完成,因此一切有可能讀取遠程資源的方案都可以成為預加載資源的方案,大致有以下幾類:
常規(guī)方式
-
使用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
非常規(guī)方式
-
使用背景圖片:
<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); }
方法有很多,也可能會有更多,具體的使用方式就不詳細說明了,具體需要注意的細節(jié)會在后文詳細描述。
預加載資源方式的評估指標
每一種方式或多或少都有其長處和缺點,本次主要按以下幾個維度進行評估:
評估中出現(xiàn)的問題
隨著不斷深入,各種方案的缺陷也被一點點挖掘,以下是一些不太容易注意到的奇怪的問題。
script標簽
在Firefox下,當script標簽的type屬性是Firefox無法識別的腳本類型時,F(xiàn)irefox不會發(fā)送任何請求,基本上除了type="text/javascript"以外,F(xiàn)irefox都不予理睬。
img標簽以及background-image
在Firefox下,當img標簽或者background-image樣式請求的內(nèi)容返回的Content-Type不是image大類時,其響應體(Response Body)只會被接收1個包,其后的內(nèi)容全部丟棄。
Flash
對于跨域的請求,F(xiàn)lash會先讀取對方服務器上的策略xml文件,如策略文件允許跨域,則會進行加載。
object或embed標簽
在Firefox下,無論元素是否隱藏,都會提示要求安裝插件,當然這插件是找不到的。
在Chrome下,如果元素被隱藏,則不發(fā)起請求;元素未隱藏則提示安裝插件。
在下載完插件前,所有瀏覽器都不會發(fā)起請求。
但如果object標簽的type使用
text/plain
則不存在安裝插件的問題,
不過悲劇的是在IE下不會發(fā)出請求,而在Firefox和Chrome下會解析執(zhí)行HTML資源
。
需要注意的是,object元素有其特殊性,創(chuàng)建一個object元素的代價遠遠大于其他元素。
link標簽
在IE下有l(wèi)oad事件,Opera中可以定時查看readystate以確定是否完成了請求,在其他瀏覽器中則不存在。
Link Prefetch
現(xiàn)階段僅Firefox給予了支持,該功能在HTML5草案中,非常值得期待。
WebWorker
使用WebWorker加載的腳本文件會立刻被解析和執(zhí)行,雖然在worker中的global對象是帶有一定限制的,但依舊無法完全阻止第三方腳本注入有害的代碼。
@font-face
@font-face僅在樣式表中定義是不會發(fā)起請求的,必須創(chuàng)建一個元素,將其font-family設為該font-face,并且該元素必須被添加到DOM樹中才會產(chǎn)生請求。
評估表格及基本判斷
表格從前文所述的A-F共6個方面來考察各種預加載資源的方式,以期較為直觀地去評價各種方式的優(yōu)劣。
從表格展現(xiàn)的數(shù)據(jù)來看,link+media的方式以及css @import方式都比較優(yōu)秀,唯一的遺憾是無法獲得其是否加載完成,因此需要站點自身通過研究用戶的行為,保證用戶2次操作的間隔足夠完成資源的加載。
其他考慮
- Link Prefetch作為HTML5草案中的標準,且瀏覽器底層級別支持,因此瀏覽器可以在帶寬空余地時候才進行預加載,用戶也可以通過一定的方式關閉該功能,各方面都有不俗的表現(xiàn),如果可以推廣到主流瀏覽器,應該是作為最值得推薦的方案。
- @import需要服務器端輔助,將需要加載的資源打包成一個css格式的文件,文件中包含若干個@import聲明,但是無論如何,瀏覽器會需要多一個請求用于加載這個動態(tài)生成的css文件。
- link+media的方式中,可以通過修改link的href屬性,使用一個link加載多個資源,不會因為標簽過多導致DOM結構的臃腫以至于影響性能。
- 在IE下,使用link+media的方式,無論下載來的內(nèi)容是否被解析,IE會對頁面進行一次redraw,這一次redraw的性能損失非常小,大致只是進入了redraw方法,但并沒有真正地重新進行布局。
-
object標簽必須與DOM樹相連才會加載資源,使用object標簽時,在非IE瀏覽器下,可以將object標簽的寬和高均設為0,但IE不行。在IE中可以將寬高均設為1,并使用
visibility: hidden; position: absolute; top: 0; z-index: -1000;
的樣式來將其隱藏。當然既然IE不會發(fā)起請求,就怎么設也沒意義了……
結論?
根據(jù)使用場景的不同,不會有一種萬能的最佳解決方案,但大致可以總結如下:
- 加載同域資源,使用XMLHttpRequest即可。
- 加載第三方可信任的資源,如同公司內(nèi)不同系統(tǒng),可以使用iframe加載非HTML資源。
- 加載圖片資源,使用img是最好的方式,但需要注意 在請求過程中img不能被GC回收 。
- 對于第三方的不可信任型資源,考慮使用link+media的方式加載,但無法確定加載完成的時間點。
- 如果可以判斷瀏覽器,針對Firefox使用Link Prefetch,針對IE使用img標簽,其他瀏覽器使用script標簽算是一種較為完美的解決方案。
- 從未來看,Link Prefetch必將是大勢所趨,大家給 WHATWG 提意見,讓他加上onload吧。
?
更多文章、技術交流、商務合作、聯(lián)系博主
微信掃碼或搜索:z360901061

微信掃一掃加我為好友
QQ號聯(lián)系: 360901061
您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點擊下面給點支持吧,站長非常感激您!手機微信長按不能支付解決辦法:請將微信支付二維碼保存到相冊,切換到微信,然后點擊微信右上角掃一掃功能,選擇支付二維碼完成支付。
【本文對您有幫助就好】元
