用javascript预加载图片、css、js的方法研究
用javascript预加载图片、css、js的方法研究
预加载的好处可以让网页更快的呈现给用户,缺点就是可能会增加无用的请求(但图片、css、js这些静态文件可以被缓存),如果用户访问的页面里面的css、js、图片被预加载了,用户打开页面的速度会快很多,提升用户体验。在用到一些大图片展示的时候,预加载大图是很不错的方法,图片更快的被呈现给用户。不多说了,作为一个前端攻城师都懂的,下面分享我做的测试和得到的结果。
先说需要知道的服务器返回的status code:
status-code: 200 - 客户端请求成功
status-code: 304 - 文件已经在浏览器缓存中,服务器告诉客户端,原来缓冲的文档还可以继续使用。
本文测试判断文件被是否被缓存,用的就是判断是否返回304.
下面针对预加载的几个方法,在不同的浏览器下加载img/js/css做个测试,主要包括new Image()、object、iframe。以下加载测试的js、css、图片文件,是从几个门户网站找的(为啥找几个?是为了尽可能滴测试到特殊的情况,测试中还真遇到了)。
1、测试用new Image()预加载1.1、new Image()加载- newImage().src ='http://img02.taobaocdn.com/tps/i2/T1iQhUXnxpXXXXXXXX-171-48.png';newImage().src ='http://static.paipaiimg.com/module/logo/logo_2011_02_22.png';newImage().src ='http://co.youa.baidu.com/picture/services/images/logo.png';newImage().src ='http://img1.t.sinajs.cn/t35/style/images/common/header/logoNew_nocache.png';
加载图片没啥好说的,IE6-9/CM/FF/OP/都返回304,预加载成功。
1.2、测试用new Image()加载css- newImage().src ='http://a.tbcdn.cn/p/global/1.0/global-min.css';newImage().src ='http://static.paipaiimg.com/member/activate.css';newImage().src ='http://co.youa.baidu.com/picture/services/base.css';newImage().src ='http://img1.t.sinajs.cn/t35/skin/skin_008/skin.css';
- newImage().src ='http://a.tbcdn.cn/s/kissy/1.1.6/kissy-min.js';newImage().src ='http://static.paipaiimg.com/js/pp.noticeBoard.js';newImage().src ='http://co.youa.baidu.com/picture/services/cms_core.js';newImage().src ='http://js.t.sinajs.cn/t35/miniblog/static/js/top.js';newImage().src ='http://shop.qq.com/act/static/week/fri/bang/day_1_p_0_10.js';
- var doc = document,
- ? ? ? ? obj = doc.createElement('object');
- ? ? ? ? ? ? ? ? ? ? ? ? obj.style.cssText ='position:absolute;top:-1px;width:1px;height:1px;';
- ? ? ? ? ? ? ? ? doc.body.appendChild(obj);? ? ? ?
- var doc = document,
- ? ? ? ? ifm = doc.createElement("iframe");
- ? ? ? ? ? ? ? ? ? ? ? ? ifm.style.cssText ='position:absolute;top:-10px;border:0;width:1px;height:1px;';
- ? ? ? ? ifm.scrolling ="no";
- ? ? ? ? doc.body.appendChild(ifm);
- window.onload =function(){? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? var ifmDoc = ifm.contentDocument || ifm.contentWindow.document;
- ? ? ? ? ifmDoc.open();
- ? ? ? ? ifmDoc.write('<!doctype><html><head></head><body>');
- ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ifmDoc.write('<link rel="stylesheet" href="http://localhost/123.css?2011" />');
- ? ? ? ? ifmDoc.write('<script defer src="http://localhost/123.js?2011"><\/script>');? ? ? ? ifmDoc.write('<img width="1" height="1" src="http://localhost/123.png?2011" />');
- ? ? ? ? ifmDoc.write('</body></html>');
- ? ? ? ? ifmDoc.close();
- };
然后创建新页面b.html,把要上面预加载的文件加到html里面,测试是否已经预加载。
结果:IE/FF/OP/CM都成功预加载。
需要说明的是:当打开a.html后,再刷新页面后,iframe内加载文件的情况。
FF,返回200(注意,这个200不是服务器返回的200,是请求缓存成功。因为发送请求的时间显示的是0)。
CM,显示状态是(from cache).
OP,虽然显示状态是n/a,但是也是from cache。 IE,IE自带的调试工具显示304,HttpWatch显示from cache。
测试环境:
WIN7 EN SP1:OP 11.50、IE7-9、FF 3.6/6.0、Chrome 10
XP EN SP3:IE6
XP EN SP3:IE7
XP CN SP3:IE8
工具:IE9自带的调试工具、HttpWatch、firebug、chrome自带的调试工具、Opera Dragonfly。
最后得出的结论:js预加载图片使用new Image()基本够用了。但是css、js特殊一些,使用object需要判断浏览器。如果考虑到js、css、img都能兼容实现预加载,可以考虑使用iframe。
另外,上面的方法创建iframe后,不使用write()写入要加载的文件,直接设置iframe.src = "cache.html",然后把要预加载的文件写在cache.html内也是可行的(以前看过有文章介绍新浪微博是这样做的,但是文章地址找不到了,搜索也没搜到),cache的网址我收藏了:http://tjs.sjs.sinajs.cn/miniblog2/static/html/cache.html,但是看微博的首页没找到这个,不知道在哪个页使用的。
其他预加载的一点补充
doc.createElement('script') 可以预加载js,如果js里面有对页面的操作,就会对页面产生影响。
doc.createElement('link') 可以预加载css,但是对当前页面的样式也可能会有影响。
所以这样预加载不太可取。
用ajax加载img/js/css,兼容性不错,文件可以被缓存,但是只能限制同域,所以使用范围有限。
预加载图片还可以利用CSS的背景图片实现。牛人lifesinger之前写过关于图片的HTTP请求的文章,不过他博客以前的数据没了。网上搜索到一篇转载的:http://www.cnblogs.com/mofish/archive/2011/01/18/1938570.html。 文章里面提到了用背景图和隐藏的img标签来预加载,调理很清晰。也可以作为参考。
另外,模仿新浪的cache.html自己写了个,如果喜欢把iframe作为独立文件使用的可以作为参考。
- <!DOCTYPE html><html><head><metacharset="utf-8"></head><body>
- <script>
- var win = window,
- ? ? ? ? doc = document,
- ? ? ? ? head = doc.getElementsByTagName("head")[0],
- ? ? ? ? getQuery =function(){
- ? ? ? ? ? ? ? ? var ret ={},
- ? ? ? ? ? ? ? ? ? ? ? ? sch = win.location.search,
- ? ? ? ? ? ? ? ? ? ? ? ? arr,
- ? ? ? ? ? ? ? ? ? ? ? ? tmp;
- ? ? ? ? ? ? ? ? if(sch){
- ? ? ? ? ? ? ? ? ? ? ? ? sch = sch.substr(1);
- ? ? ? ? ? ? ? ? ? ? ? ? arr = sch.split("&");
- ? ? ? ? ? ? ? ? ? ? ? ? for(var i =0, j = arr.length; i < j; i++){
- ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? tmp = arr[i].split('=');
- ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ret[tmp[0]]= tmp[1];
- ? ? ? ? ? ? ? ? ? ? ? ? }
- ? ? ? ? ? ? ? ? }
- ? ? ? ? ? ? ? ? return ret;
- ? ? ? ? },
- ? ? ? ? version = getQuery().v ||'';
- win.onerror =function(){returntrue};
- win.onload =function(){
- ? ? ? ? var b = doc.createElement("script");
- ? ? ? ? b.src ='http://xx/1.js?v='+ version;
- ? ? ? ? head.appendChild(b);
- ? ? ? ? };
- doc.write('<link rel="stylesheet" href="http://xxx/3.css?version='+ version +'" \/>');
- </script>
- <imgsrc="http://xxx/4.png"/>
- </body></html>
- newImage().src ='http://img02.taobaocdn.com/tps/i2/T1iQhUXnxpXXXXXXXX-171-48.png';newImage().src ='http://static.paipaiimg.com/module/logo/logo_2011_02_22.png';newImage().src ='http://co.youa.baidu.com/picture/services/images/logo.png';newImage().src ='http://img1.t.sinajs.cn/t35/style/images/common/header/logoNew_nocache.png';
加载图片没啥好说的,IE6-9/CM/FF/OP/都返回304,预加载成功。
1.2、测试用new Image()加载css
- newImage().src ='http://a.tbcdn.cn/p/global/1.0/global-min.css';newImage().src ='http://static.paipaiimg.com/member/activate.css';newImage().src ='http://co.youa.baidu.com/picture/services/base.css';newImage().src ='http://img1.t.sinajs.cn/t35/skin/skin_008/skin.css';
- newImage().src ='http://a.tbcdn.cn/s/kissy/1.1.6/kissy-min.js';newImage().src ='http://static.paipaiimg.com/js/pp.noticeBoard.js';newImage().src ='http://co.youa.baidu.com/picture/services/cms_core.js';newImage().src ='http://js.t.sinajs.cn/t35/miniblog/static/js/top.js';newImage().src ='http://shop.qq.com/act/static/week/fri/bang/day_1_p_0_10.js';
- var doc = document,
- ? ? ? ? obj = doc.createElement('object');
- ? ? ? ? ? ? ? ? ? ? ? ? obj.style.cssText ='position:absolute;top:-1px;width:1px;height:1px;';
- ? ? ? ? ? ? ? ? doc.body.appendChild(obj);? ? ? ?
- var doc = document,
- ? ? ? ? ifm = doc.createElement("iframe");
- ? ? ? ? ? ? ? ? ? ? ? ? ifm.style.cssText ='position:absolute;top:-10px;border:0;width:1px;height:1px;';
- ? ? ? ? ifm.scrolling ="no";
- ? ? ? ? doc.body.appendChild(ifm);
- window.onload =function(){? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? var ifmDoc = ifm.contentDocument || ifm.contentWindow.document;
- ? ? ? ? ifmDoc.open();
- ? ? ? ? ifmDoc.write('<!doctype><html><head></head><body>');
- ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ifmDoc.write('<link rel="stylesheet" href="http://localhost/123.css?2011" />');
- ? ? ? ? ifmDoc.write('<script defer src="http://localhost/123.js?2011"><\/script>');? ? ? ? ifmDoc.write('<img width="1" height="1" src="http://localhost/123.png?2011" />');
- ? ? ? ? ifmDoc.write('</body></html>');
- ? ? ? ? ifmDoc.close();
- };
然后创建新页面b.html,把要上面预加载的文件加到html里面,测试是否已经预加载。
结果:IE/FF/OP/CM都成功预加载。需要说明的是:当打开a.html后,再刷新页面后,iframe内加载文件的情况。
FF,返回200(注意,这个200不是服务器返回的200,是请求缓存成功。因为发送请求的时间显示的是0)。
CM,显示状态是(from cache).
OP,虽然显示状态是n/a,但是也是from cache。 IE,IE自带的调试工具显示304,HttpWatch显示from cache。测试环境:
WIN7 EN SP1:OP 11.50、IE7-9、FF 3.6/6.0、Chrome 10
XP EN SP3:IE6
XP EN SP3:IE7
XP CN SP3:IE8
工具:IE9自带的调试工具、HttpWatch、firebug、chrome自带的调试工具、Opera Dragonfly。最后得出的结论:js预加载图片使用new Image()基本够用了。但是css、js特殊一些,使用object需要判断浏览器。如果考虑到js、css、img都能兼容实现预加载,可以考虑使用iframe。
另外,上面的方法创建iframe后,不使用write()写入要加载的文件,直接设置iframe.src = "cache.html",然后把要预加载的文件写在cache.html内也是可行的(以前看过有文章介绍新浪微博是这样做的,但是文章地址找不到了,搜索也没搜到),cache的网址我收藏了:http://tjs.sjs.sinajs.cn/miniblog2/static/html/cache.html,但是看微博的首页没找到这个,不知道在哪个页使用的。
其他预加载的一点补充
doc.createElement('script') 可以预加载js,如果js里面有对页面的操作,就会对页面产生影响。
doc.createElement('link') 可以预加载css,但是对当前页面的样式也可能会有影响。
所以这样预加载不太可取。
用ajax加载img/js/css,兼容性不错,文件可以被缓存,但是只能限制同域,所以使用范围有限。
预加载图片还可以利用CSS的背景图片实现。牛人lifesinger之前写过关于图片的HTTP请求的文章,不过他博客以前的数据没了。网上搜索到一篇转载的:http://www.cnblogs.com/mofish/archive/2011/01/18/1938570.html。 文章里面提到了用背景图和隐藏的img标签来预加载,调理很清晰。也可以作为参考。另外,模仿新浪的cache.html自己写了个,如果喜欢把iframe作为独立文件使用的可以作为参考。
- <!DOCTYPE html><html><head><metacharset="utf-8"></head><body>
- <script>
- var win = window,
- ? ? ? ? doc = document,
- ? ? ? ? head = doc.getElementsByTagName("head")[0],
- ? ? ? ? getQuery =function(){
- ? ? ? ? ? ? ? ? var ret ={},
- ? ? ? ? ? ? ? ? ? ? ? ? sch = win.location.search,
- ? ? ? ? ? ? ? ? ? ? ? ? arr,
- ? ? ? ? ? ? ? ? ? ? ? ? tmp;
- ? ? ? ? ? ? ? ? if(sch){
- ? ? ? ? ? ? ? ? ? ? ? ? sch = sch.substr(1);
- ? ? ? ? ? ? ? ? ? ? ? ? arr = sch.split("&");
- ? ? ? ? ? ? ? ? ? ? ? ? for(var i =0, j = arr.length; i < j; i++){
- ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? tmp = arr[i].split('=');
- ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ret[tmp[0]]= tmp[1];
- ? ? ? ? ? ? ? ? ? ? ? ? }
- ? ? ? ? ? ? ? ? }
- ? ? ? ? ? ? ? ? return ret;
- ? ? ? ? },
- ? ? ? ? version = getQuery().v ||'';
- win.onerror =function(){returntrue};
- win.onload =function(){
- ? ? ? ? var b = doc.createElement("script");
- ? ? ? ? b.src ='http://xx/1.js?v='+ version;
- ? ? ? ? head.appendChild(b);
- ? ? ? ? };
- doc.write('<link rel="stylesheet" href="http://xxx/3.css?version='+ version +'" \/>');
- </script>
- <imgsrc="http://xxx/4.png"/>
- </body></html>