什么是预加载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不会发起请求,就怎么设也没意义了…… 根据使用场景的不一样,不会有一种万能的最佳解决方案,但大体能够总结以下: