2週間ほど前に入手したSteve Sounders氏の新刊「」ですが、ようやく本格的に読み始めました。
前の「」は発刊前にネット上で読んでいたのでスルーしてしまいましたが、今回はちゃんと購入。前のものが基本をしっかりと抑えた王道的内容だったのに比べて、比較的トリッキーなテクニックが増えているように思います。
今回は本書の5章から「へー」と思った、外部スクリプトを他のファイルのロードを妨げることなく取得し、なおかつそのファイルのロードが終わった際に後続のスクリプトが実行されるための方法(複雑)を確認してみます。
SCRIPTタグを減らすテクニック
この技法はまず、jQueryの作者であるJohn Resig氏のblogポスト Degrading Script Tags に端を発します。
まず、次のコードを見て下さい。
これを、次のように書けたら幸せだよね、という話。
jQuery("div").text("loaded!");
これなら、SCRIPTタグが少なくて済むし、コードの依存関係もハッキリする。srcに記述されたファイルのロードが失敗したら中身のコードが実行されない形なら、万が一の場合にもスクリプトエラーにならずに済むと。
次のようなコードを外部ファイル(この例で言えばjquery.js)の最後に加えれば、これが実装できます。
(function(){ var scripts = document.getElementsByTagName("script"); var curScript = scripts[ scripts.length - 1 ]; if ( curScript.executed ) return; // ... jQuery ... curScript.executed = true; var script = curScript.innerHTML; if ( script ) { jQuery(document).ready(function(){ jQuery.globalEval( script ); }); } })();
もちろんこれは、jQuery以外のライブラリでも適用可能な、非常にクールな手法です。
正直なところ、自分は最初のこのポストが投稿された際にはそれほど感銘を受けなかった記憶があります。それは「スクリプトのロードと実行が連動する」点に私が着目できていなかったからで、単にscriptタグを減らせるシンタックス程度の認識しかありませんでした。
今回改めて読み返してみて、直観的な良い記述方法だなと思いました。
他ファイルのロードブロック問題
見たように素晴らしいテクニックなのですが、この方法にもまだパフォーマンスの観点から改善の余地があるとSteve Sounders氏は指摘しています。
それが、スクリプトのダウンロードが他の外部ファイルのダウンロードをブロックしてしまう問題の回避についてです。
前述のテクニックはjsファイルのロードについては通常の方法であるため、ブロックは発生してしまいます。これを避け、なおかつロード完了とスクリプト実行がきちんと連動するように改良されたスクリプトが、こちらで紹介されています。
function init(){ jQuery("div").text("loaded!"); } var domscript = document.createElement('script'); domscript.src = "jquery.js"; if ( -1 != navigator.userAgent.indexOf('Opera')){ domscript.innerHTML = 'init();'; }else{ domscript.text = 'init();'; } document.getElementsByTagName('head')[0].appendChild(domscript);
この呼び出し方と前述のテクニックを組み合わせることで、高速な外部ファイル呼び出しと、そのロード完了に依存するスクリプトの記述が可能になります。
但し、この方法を使うには外部ファイル側に自要素の中身をコールバック(?)する仕組みを埋め込まなければならず、汎用的に使うのは難しくなってしまいます。
将来的にこの記述をブラウザ側がサポートしてくれた場合であればまだしも、現時点では同書の別項で紹介されているOnload技法の方が優れているとしています。
こちらの検証は、また機会があれば。
Related posts: