什麼是預加載javascript
所謂預加載,就是經過必定的編程方法,使瀏覽器在空間的時候,在後臺經過HTTP請求訪問某些資源。當用戶在一段時間後真正使用這些資源的時候,相比一個完整的(返回200)的請求,能夠更快地得到這些資源(返回304或者直接命中瀏覽器緩存)。css
預加載在部分狀況下有着十分重要的意義,特別是當肯定某些資源用戶在短期內會使用,如分頁列表的上一頁和下一頁、以及一些經常使用的LOGO之類的圖片等。html
預加載的原理就是想辦法發送一個HTTP請求,對響應的緩存等都由瀏覽器完成,所以一切有可能讀取遠程資源的方案均可以成爲預加載資源的方案,大體有如下幾類:java
<script type="other/prefetch" src="some.res"></script>
<img src="some.res" />
<iframe src="some.res"></iframe>
$.get('some.res');
<div style="background-image: url(some.res);"></div>
<object type="other/prefetch" src="some.res"></object>
<link rel="stylesheet" href="some.res" media="prefetch" />
@import "some.res"
<link rel="prefetch" href="some.res" />
var worker = new Worker('some.res');
@font-face { font-family: prefetch; src: url(some.res); }
方法有不少,也可能會有更多,具體的使用方式就不詳細說明了,具體須要注意的細節會在後文詳細描述。編程
每一種方式或多或少都有其長處和缺點,本次主要按如下幾個維度進行評估:跨域
隨着不斷深刻,各類方案的缺陷也被一點點挖掘,如下是一些不太容易注意到的奇怪的問題。瀏覽器
在Firefox下,當script標籤的type屬性是Firefox沒法識別的腳本類型時,Firefox不會發送任何請求,基本上除了type="text/javascript"之外,Firefox都不予理睬。緩存
在Firefox下,當img標籤或者background-image樣式請求的內容返回的Content-Type不是image大類時,其響應體(Response Body)只會被接收1個包,其後的內容所有丟棄。安全
對於跨域的請求,Flash會先讀取對方服務器上的策略xml文件,如策略文件容許跨域,則會進行加載。服務器
在Firefox下,不管元素是否隱藏,都會提示要求安裝插件,固然這插件是找不到的。
在Chrome下,若是元素被隱藏,則不發起請求;元素未隱藏則提示安裝插件。
在下載完插件前,全部瀏覽器都不會發起請求。
但若是object標籤的type使用text/plain
則不存在安裝插件的問題,不過悲劇的是在IE下不會發出請求,而在Firefox和Chrome下會解析執行HTML資源。
須要注意的是,object元素有其特殊性,建立一個object元素的代價遠遠大於其餘元素。
在IE下有load事件,Opera中能夠定時查看readystate以肯定是否完成了請求,在其餘瀏覽器中則不存在。
現階段僅Firefox給予了支持,該功能在HTML5草案中,很是值得期待。
使用WebWorker加載的腳本文件會馬上被解析和執行,雖然在worker中的global對象是帶有必定限制的,但依舊沒法徹底阻止第三方腳本注入有害的代碼。
@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次操做的間隔足夠完成資源的加載。
visibility: hidden; position: absolute; top: 0; z-index: -1000;
的樣式來將其隱藏。固然既然IE不會發起請求,就怎麼設也沒意義了…… 根據使用場景的不一樣,不會有一種萬能的最佳解決方案,但大體能夠總結以下: