javascriptでピクチャ,css,jsをプリロードする方法の研究

10004 ワード

プリロードの利点は、Webページをより速くユーザーに提示することができます.欠点は、無駄なリクエストを増やす可能性があることです(ただし、画像、css、jsなどの静的ファイルはキャッシュされます).ユーザーがアクセスしたページのcss、js、画像がプリロードされると、ユーザーがページを開く速度が速くなり、ユーザー体験が向上します.いくつかの大きな画像を表示するときに、大きな図をプリロードするのは良い方法で、画像はより速くユーザーに表示されます.多くは言わないで、1つの先端の城を攻める師としてすべて知っていて、以下は私のしたテストと得た結果を分かち合います.
まず、サーバが返すstatus code:status-code:200-クライアント要求成功status-code:304-ファイルはブラウザキャッシュにあり、サーバはクライアントに元のバッファされたドキュメントが引き続き使用できることを伝えます.本稿では、ファイルがキャッシュするか否かを判断する、304を返すか否かを判断する.
次に、new Image()、object、iframeを含む、異なるブラウザでimg/js/cssをロードするいくつかの方法についてテストします.以下にテストをロードするjs、css、ピクチャファイルは、いくつかのポータルサイトから探しています(なぜいくつ探していますか?できるだけ特殊な状況までテストするために、テスト中に本当に遭遇しました).

1、試験用new Image()プリロード


1.1、new Image()ロード



new Image().src = 'http://img02.taobaocdn.com/tps/i2/T1iQhUXnxpXXXXXXXX-171-48.png'; //  

new Image().src = 'http://static.paipaiimg.com/module/logo/logo_2011_02_22.png'; //  

new Image().src = 'http://co.youa.baidu.com/picture/services/images/logo.png'; //  

new Image().src = 'http://img1.t.sinajs.cn/t35/style/images/common/header/logoNew_nocache.png'; //  */


次に画像をページに追加します:
ロード画像は何も言うことはありませんが、IE 6-9/CM/FF/OP/は304に戻り、プリロードに成功しました.

1.2、試験用new Image()でcssをロードする



new Image().src = 'http://a.tbcdn.cn/p/global/1.0/global-min.css'; //  (1)

new Image().src = 'http://static.paipaiimg.com/member/activate.css'; //  (2)

new Image().src = 'http://co.youa.baidu.com/picture/services/base.css'; //  (3)

new Image().src = 'http://img1.t.sinajs.cn/t35/skin/skin_008/skin.css'; //  (4)

// http://auto.sina.com.cn/css/newstyles.css

//        IE Expires              


さらにcssをページに追加
これには違いがあります.CM/OPは、Expiresが設定されているかどうかにかかわらず304を返します.FFは、全て200を返しました.IE,1/2/4はいずれも304を返し,3は200を返す.返されたHTTP-Headerと比較すると、1/2/4にExpiresの有効期限が設定されており、3には設定されていません.説明IEの下でキャッシュするにはExpiresを設定する必要があり(かつ設定時間は現在時間より大きい)、FFはnew Image()のプリロードをサポートしない.

1.3、テスト用new Image()でjsをロードする



new Image().src = 'http://a.tbcdn.cn/s/kissy/1.1.6/kissy-min.js'; //  (1)

new Image().src = 'http://static.paipaiimg.com/js/pp.noticeBoard.js'; //  (2)

new Image().src = 'http://co.youa.baidu.com/picture/services/cms_core.js'; //  (3)

new Image().src = 'http://js.t.sinajs.cn/t35/miniblog/static/js/top.js'; //  (4)

new Image().src = 'http://shop.qq.com/act/static/week/fri/bang/day_1_p_0_10.js'; //QQ(5)


さらにjsをページに追加します.
CM/OPは、いずれも304 FFを返し、5のみ304を返し、5のみのHTTP-Headerが最も簡単(Date、Server、Expires、Cache-Controlを含む)である.他のいくつかの応答ヘッダ情報の内容は比較的多いが,いずれも5のうちのいくつかを設定している.法則を探して、他のいくつかの応答ヘッダがあることを発見しました:Content-Type:text/javascript、5の中にこれがありません.IE,2/5は304を返し,1/3/4は200を返し,応答ヘッダと比較してもContent-Typeの影響を受けるはずであり,IEの2/5はContent-Typeを見ていない.また、AndrewZhang(http://www.cnblogs.com/AndyWithPassion/IE下imageプリロードjsはhttpwatch下でcontentを表示し、リソースのロードは完全ではないと述べた.私のところのテストもそうです.バイト制限があるようで、テストでは2が完全に返され、5の一部が失われました.だからnew ImageでJSをロードするのは少しも望ましくありません.
ここでまとめてみると、プリロード画像はnew Image()で互換性は問題ありません.しかしcss/jsはOP/CMのみで可能であり、IE/FFは基本的に無効である(この点、IE/FFは非常に暗黙の了解がある).

2、テスト用objectプリロード



var doc = document,

	obj = doc.createElement('object');

	//obj.data = '123.js'; //Ps:    OP   (  data     object    text node)

	//obj.setAttribute('data', '123.js'); // img、css、js

	obj.style.cssText = 'position:absolute;top:-1px;width:1px;height:1px;'; 

	// obj.style.width = obj.style.height = 0;

	doc.body.appendChild(obj); //   object         head  ,     */

	//obj.onload = function(){ alert('loaded') }; // FF/OP/Webkit  (  data   ,IE9   )


次にobjectにdataがロードされたファイルを作成し、HTML内のテストにラベルを追加します.
試験結果:FF/OP/CM:img/js/cssはいずれも304に戻る.IE 6-8:objectでimg/js/cssをロードすると、直接Abortedになります.IE 9は比較的特殊である:IE 9はjs/cssをロードし、HTTP 200に戻ってからAbortedを要求し、ここでは実際に1回(2回目のAborted)を要求する.IE 9がimgをロードする場合は、HTTP 200を要求してからピクチャの返却を要求するので、ピクチャは2回要求する必要がある.
IE 9の1回目のリクエストで返されたコンテンツは空である(このときブラウザは一般的に引っかかったり、直接応答を失ったりする).IE 9はまずurlを要求し,ファイルタイプを取得し,JS/CSSがAbortedであると判断し,ピクチャであると判断してロードする.
IE 9の第1回目のリクエストは、HTTPヘッダ情報を読み取ってファイルタイプを取得したり、こっそりファイルをダウンロードしたりして、砂箱の中でファイルタイプをテストしたりします.興味深いことに、例えばobjectでJSをロードすると、IE 9もロードできることがあります.つまり、1番目のリクエストでファイルがJSだと判断できなかったことがあります(これを見たいのは運次第ですが、ネットの速度が遅いときに発生する可能性があります).
以前はIEはファイル接尾辞でファイルタイプを判断していたが、後期はHTTPヘッダ情報で判断しても偽造できるため、objectはIEの下でセキュリティの問題があったという.IE 6/7、ファイル接尾辞が.js/.cssはリクエストを発行しません.http://xxx/test.js?123.pngと、リクエストを送信し、scriptタグで導入して、キャッシュされることを発見しました(cssはそうしてもOK^^).IE 8は、js/cssに接尾辞を付けてもリクエストは発行されず、pngに変更するとリクエストを発行してコンテンツを得ることができ、ページ作成ラベルが導入され、ファイルがキャッシュされていない.しかし、ファイルが本物の画像であればキャッシュされます.余談ですが、IEのアップグレードに伴い、セキュリティも向上していることがわかります.
So,ここでの結論は:FF/OP/CMの下でobjectでプリロードすることができて、IEはくれぐれも使わないでください.

3、テスト用iframeプリロード


まずページa.htmlを作成し、次のjsを追加します.


var doc = document,

	ifm = doc.createElement("iframe");

	//ifm.id="preLoadIfm";

	// ifm.style.border = ifm.width = ifm.height = 0;

	ifm.style.cssText = 'position:absolute;top:-10px;border:0;width:1px;height:1px;';

	ifm.scrolling = "no";

	doc.body.appendChild(ifm);



window.onload = function(){ //         window.onload    

	//   onload,   appendChild,    onload(      ,IE     )

	// ifm.onload = function(){ alert('ifm loaded'); }

	// contentWindow.document-     ,contentDocument-IE9/FF/OP/CM  

	var ifmDoc = ifm.contentDocument || ifm.contentWindow.document;

	ifmDoc.open();

	ifmDoc.write('<!doctype><html><head></head><body>');

	//ifmDoc.write('<style>html{background:#000;color:#fff}</style>'); //     

	//ifmDoc.write('<script>alert("a")<\/script>'); //     

	//ifmDoc.write('<p>test</p><p>test</p><p>test</p><p>test</p><p>test</p>');//     

	//     

	ifmDoc.write('<link rel="stylesheet" href="http://localhost/123.css?2011" />');

	ifmDoc.write('<script defer src="http://localhost/123.js?2011"><\/script>'); //  defer,    IE  。。

	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.
試験環境:WIN 7 EN SP 1:OP 11.50、IE 7-9、FF 3.6/6.0、Chrome 10 XPEN SP 3:IE 6 XPEN SP 3:IE 7 XP CN SP 3:IE 8ツール:IE 9が持参したデバッグツール、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リクエストの文章を書いたことがありますが、彼のブログの前のデータはありません.ネット上で1篇の転載を検索しました:http://www.cnblogs.com/mofish/archive/2011/01/18/1938570.html. 背景図と隠れたimgラベルでプリロードし,調理がはっきりしていると述べた.参考にもなります.
また、新浪のcacheを真似します.htmlは自分で書いたので、iframeを独立したファイルとして使うのが好きなら参考にしてもいいです.


<!DOCTYPE html><html><head><meta charset="utf-8"></head><body>

<script>

//usage: cache.html?v=123

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(){return true}; //  js    



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>

<img src="http://xxx/4.png" />

</body></html>