JavaScript_javascript スキルのノンブロッキング読み込みパフォーマンス最適化ソリューション

WBOY
リリース: 2016-05-16 16:34:37
オリジナル
1287 人が閲覧しました

ブラウザにおける Javascript のパフォーマンスは、フロントエンド開発者が直面する最も重要なユーザビリティの問題であると言えます。

Yahoo の Yslow 23 ルールのうち、その 1 つは JS を最後に置くことです。その理由は、実際には、ほとんどのブラウザーは単一のプロセスを使用して UI や Javascript の更新などの複数のタスクを処理し、一度に 1 つのタスクしか実行できないためです。 JavaScript の実行時間と、ブラウザーがユーザー操作に応答するためにアイドル状態になるまでの待機時間。

基本的なレベルでは、これは <script> タグの存在により、ページ全体がスクリプトの解析と実行を待機することを意味します。実際の JavaScript コードがインラインであるか、無関係な外部ファイルに含まれているかに関係なく、ページのダウンロードと解析のプロセスは停止し、スクリプトがこの処理を完了するまで待ってから続行する必要があります。スクリプトは実行中にページのコンテンツを変更する可能性があるため、これはページのライフサイクルの重要な部分です。典型的な例は、document.write() 関数です。例: <br> </p> <div class="codetitle"> <span><a style="CURSOR: pointer" data="5199" class="copybut" id="copybut5199" onclick="doCopy('code5199')"><u>コードをコピー</u></a></span> コードは次のとおりです:</div> <div class="codebody" id="code5199"> <br> <html><br> <頭><br> <title>スクリプトの例</title><br> </頭> <br> <br> <br> <p><br> <script type="text/javascript"><br> document.write("日付は " (new Date()).toDateString());<br>                                                                                                 </p><br> </本文> <br> </html><br> <br> </div> 上記の HTML ページのように、ブラウザが <script> タグに遭遇した場合、JavaScript が <p> タグにコンテンツを追加するかどうかを予測する方法はありません。したがって、ブラウザは停止し、この JavaScript コードを実行し、ページの解析と翻訳を続行します。 src 属性を使用して JavaScript をロードするときにも同じことが起こります。ブラウザーはまず外部ファイルのコードをダウンロードする必要がありますが、これには時間がかかり、次にコードを解析して実行します。このプロセス中、ページの解析とユーザーの操作は完全にブロックされます。 <br> スクリプトは他のページ リソースのダウンロード プロセスをブロックするため、すべての <script> タグをできるだけ <body> タグの最後に配置して、全体のダウンロードへの影響を最小限に抑えることをお勧めします。ページ。例: <p> <br></p> <div class="codetitle"><span><a style="CURSOR: pointer" data="96913" class="copybut" id="copybut96913" onclick="doCopy('code96913')">コードをコピー<u></u></a> コードは次のとおりです:</span></div> <div class="codebody" id="code96913"> <html><br> <頭><br> <title>スクリプトの例</title><br> <link rel="stylesheet" type="text/css" href="styles.css"> </head><br> <br> <br> <p>Hello world!</p><br> <-- 推奨されるスクリプトの配置の例 --> <br /> <script type="text/javascript" src="file1.js"></script>





このコードは、HTML ファイル内の <script> タグの推奨される場所を示しています。スクリプトのダウンロードは相互にブロックしますが、ページはダウンロードされてユーザーの目の前に表示されており、ページに入る速度はそれほど遅いようには見えません。これは、JS を一番下に置くことについて上で述べたものです。 <br> </div>さらに、Yahoo! は、「Yahoo! ユーザー インターフェイス (YUI)」ライブラリの「ユニオン ハンドル」を作成し、これは「コンテンツ配信ネットワーク (CDN)」を通じて実装されます。どの Web サイトでも、「ユニオン ハンドル」URL を使用して、YUI パッケージ内のどのファイルが含まれているかを示すことができます。たとえば、次の URL には 2 つのファイルが含まれています: <p></p> <p><br>コードをコピー</p> <div class="codetitle"><span><a style="CURSOR: pointer" data="74887" class="copybut" id="copybut74887" onclick="doCopy('code74887')"> コードは次のとおりです:<u><div class="codebody" id="code74887"> <br> <script type="text/javascript" src="http://yui.yahooapis.com/combo?2.7.0/build/yahoo/yahoo-min.js&2.7.0/build/event/event-min.js "></script>

この URL は、2.7.0 バージョンの yahoo-min.js および events-min.js ファイルを呼び出します。これらのファイルはサーバー上では 2 つの別個のファイルですが、サーバーがこの URL リクエストを受信すると、2 つのファイルはマージされてクライアントに返されます。この方法では、2 つの <script> タグ (それぞれがファイルをロードする) は必要なく、1 つの <script> タグでそれらをロードできます。これは、HTML ページに複数の外部 Javascript を含める最良の方法です。 </p> <p><strong>ノンブロッキング スクリプト ノンブロッキング スクリプト</strong></p> <p>上記は、ページの初期状態で複数の Javascript スクリプトをロードするための最良の方法です。 Javascript は、http リクエストやインターフェイスの更新などの特定のブラウザ プロセスをブロックする傾向があります。これは、開発者が直面する最も重大なパフォーマンス上の問題です。 JavaScript ファイルを短くし、http リクエストの数を制限することは、応答性の高い Web アプリケーションを作成するための最初のステップにすぎません。 </p> <p>しかし、大量の JS コードを含む大規模な Web ページなどでは、ソース コードを短くすることが常に最良の選択であるとは限りません。そこで、ブラウザをある程度ブロックせずに、ページに JavaScript を徐々に追加するノンブロッキング スクリプトが登場しました。 </p> <p>スクリプトをブロックしないための鍵は、JavaScript ソース コードをロードする前にページのロードが完了するのを待つことです。つまり、ウィンドウのロード イベントが発行された後にコードのダウンロードを開始します。 </p> <p>関連説明: </p> <p>ウィンドウのロードイベントは、ページがロードされた後に一度だけトリガーされます。 <br> window.onload=function(){} は、Web ページ内のすべてのコンテンツ (画像などの要素に関連するすべてのファイルを含む) が読み込まれるまで待機する必要があります。つまり、JavaScript は、Web ページ内の要素にのみアクセスできます。この時のページです。 </p> <p>いくつかの方法は次のとおりです: </p> <p><strong>遅延スクリプト 遅延スクリプト</strong></p> <p>HTML4 では、<script> タグの拡張属性 defer が定義されています。 </script>

この defer 属性は、要素に含まれるスクリプトが DOM を変更することを目的としていないため、コードを後で実行できることを示します。 defer 属性は Internet Explorer 4 と Firefox 3.5 でのみサポートされているため、理想的なクロスブラウザー ソリューションではありません。他のブラウザでは、defer 属性は無視されます。したがって、<script> タグは通常のデフォルトの方法で処理され、ブロックが発生します。すべての主要なブラウザでサポートされている場合でも、これは依然として効果的なソリューションです。 <br> </p> <div class="codetitle"> <span><a style="CURSOR: pointer" data="14408" class="copybut" id="copybut14408" onclick="doCopy('code14408')"><u>コードをコピー</u></a></span> コードは次のとおりです:</div> <div class="codebody" id="code14408"> <br> <script type="text/javascript" src="file1.js" defer></script>

defer 属性を持つ <script> タグはドキュメント内のどこにでも配置でき、DOM がロードされるまで (onload イベント ハンドラーが呼び出される前に) 解析されながらダウンロードを開始します。遅延 Javascript ファイルがダウンロードされるとき、ブラウザによる他の処理はブロックされないため、ファイルは他のリソースと並行してダウンロードできます。 </p> <p>次のコードを使用して、ブラウザが defer 属性をサポートしているかどうかをテストできます。<br> </p> <div class="codetitle"> <span><a style="CURSOR: pointer" data="95845" class="copybut" id="copybut95845" onclick="doCopy('code95845')"><u>コードをコピー</u></a></span> コードは次のとおりです:</div> <div class="codebody" id="code95845"> <br> <html><br> <頭><br> <title>スクリプト遅延の例</title><br> </頭> <br> <br> <br> <スクリプト遅延>アラート("遅延");</スクリプト> <スクリプト>アラート("スクリプト"); <br> <script> window.onload = function(){alert("load");}; </本文> <br> </html><br> <br><br> </div>ブラウザが遅延をサポートしていない場合、ポップアップ ダイアログ ボックスの順序は「遅延」、「スクリプト」、「ロード」になります。 <p>ブラウザが遅延をサポートしている場合、ポップアップ ダイアログ ボックスの順序は「スクリプト」、「ロード」、「遅延」になります。 </p> <p></p>動的スクリプト要素 動的スクリプト要素<p><strong> </strong>DOM を使用すると、JavaScript を使用して HTML 内のほとんどすべてのドキュメント コンテンツを動的に作成できます。</p> という標準 DOM を使用して、新しい <script> 要素を作成できます。 <p></p> <p></p> <div class="codetitle"><span>コードをコピーします<a style="CURSOR: pointer" data="78091" class="copybut" id="copybut78091" onclick="doCopy('code78091')"><u></u> コードは次のとおりです:</a></span></div> 1 var script = document.createElement ("script");<div class="codebody" id="code78091"> 2 script.type = "text/javascript";<br> 3 script.src = "file1.js"; 4 document.body.appendChild(script);<br> <br> <p>新しい <script> 要素は file1.js ソース ファイルを読み込みます。このファイルは、要素がページに追加されるとすぐにダウンロードを開始します。このテクノロジーの重要な点は、ダウンロードがどこで開始されたとしても、他のページの処理をブロックすることなくファイルがダウンロードされて実行されることです。 </script>

動的スクリプト ノードを使用してファイルがダウンロードされると、返されたコードは通常、すぐに実行されます (Firefox と Opera は除きます。Firefox と Opera は、以前のすべての動的スクリプト ノードの実行が完了するまで待機します)。

ほとんどの場合、JavaScript ファイルを動的にダウンロードする関数を呼び出したいと考えています。次の関数パッケージは、標準実装と IE 実装を実装します:

コードをコピーします コードは次のとおりです:

関数loadScript(url, callback){
var script = document.createElement ("script") ;
script.type = "text/javascript";

If (script.readyState){ //IE
script.onreadystatechange = function(){
If (script.readyState == "ロード済み" || script.readyState == "complete"){
script.onreadystatechange = null;
コールバック(); }
};
}
else { //その他
script.onload = function(){ callback();
};
}
Script.src = url;
Document.getElementsByTagName("head")[0].appendChild(script); }

loadScript("file1.js", function(){ //
を呼び出す alert("ファイルが読み込まれました!"); });



この関数は、JavaScript ファイルの URL と、JavaScript の受信が完了したときにトリガーされるコールバック関数の 2 つのパラメーターを受け取ります。プロパティ検査は、どのイベントを監視するかを決定するために使用されます。最後のステップは、src 属性と JavaScript ファイルを head に追加することです。
動的スクリプト読み込みは、ブラウザー間で動作し、シンプルで使いやすいため、ノンブロッキング Javascript ダウンロードで最も一般的に使用されるモードです。

XMLHttpRequest スクリプトインジェクション XHR スクリプトインジェクション

非ブロック的な方法でスクリプトを取得するもう 1 つの方法は、XMLHttpRequest (XHR) オブジェクトを使用してスクリプトをページに挿入することです。この手法では、まず XHR オブジェクトを作成し、次に JavaScript ファイルをダウンロードし、次に動的 <script> 要素を使用して JavaScript コードをページに挿入します。デモを見る: </script>

コードをコピーします コードは次のとおりです: var xhr = 新しい XMLHttpRequest(); xhr.open("get", "file1.js", true); xhr.onreadystatechange = function(){
If (xhr.readyState == 4){
If (xhr.status >= 200 && xhr.status var script = document.createElement("script"); script.type = "text/javascript";
script.text = xhr.responseText;
document.body.appendChild(script);
}
}
};
xhr.send(null);

このコードは、file1.js を取得するためにサーバーにファイル取得リクエストを送信します。 onreadystatechange イベント ハンドラーは、readyState が 4 であるかどうかを確認し、次に http ステータス コードが有効であるかどうかを確認します (200 はクライアント要求が成功したことを示し、2xx は有効な応答を示し、304 はキャッシュされた応答を示します)。有効な応答を受信した場合、新しい <script> 要素が作成され、その text 属性がサーバーから受信した responseText 文字列に設定されます。これを実行すると、実際にはインライン コードを含む <script> 要素が作成され、新しい <script> 要素がドキュメントに追加されると、コードが実行されて使用できるようになります。 </p> <p>この方法の利点は、互換性が高く、すぐには実行されない Javascript コードをダウンロードできることです。コードは <script> タグの外側で返されるため、ダウンロード後に自動的に実行されず、実行を延期できます。 </p> <p>このメソッドの決定には、ブラウザーの同一オリジン制限が適用されます。JavaScript ファイルはページと同じドメインに配置する必要があり、CDN (コンテンツ配信ネットワーク) からダウンロードすることはできません。このため、大規模な Web ページでは通常、XHR スクリプト インジェクション テクノロジは使用されません。 </p> <p><strong>推奨される非ブロッキング パターン 推奨される非ブロッキング パターン</strong></p> <p>大量の Javascript をページにロードする推奨方法は、2 段階のプロセスです: </p> <p>最初のステップには Javascript を動的にロードするために必要なコードが含まれており、次にページの初期化に必要な Javascript 以外の部分をロードします。コードのこの部分はできる限り小さくする必要があり、loadScript() 関数のみを含めることができます。この部分はダウンロードと実行が非常に速く、ページにあまり干渉しません。 </p> <p>2 番目のステップでは、初期コードの準備ができたら、それを使用して残りの Javascript をロードします。 </p> <p>例: <br> </p> <div class="codetitle"> <span><a style="CURSOR: pointer" data="91573" class="copybut" id="copybut91573" onclick="doCopy('code91573')"><u>コードをコピー</u></a></span> コードは次のとおりです:</div> <div class="codebody" id="code91573"> <br> 1 <script type="text/javascript" src="loader.js"><br> 2 </script>


このコードを body の終了タグの前に配置します。これを行う利点は、まず、JavaScript の実行が他のページの他の部分の表示に影響を与えないことです。次に、JavaScript ファイルの 2 番目の部分がダウンロードされると、アプリケーションに必要なすべての DOM が作成され、アクセスできる状態になります。これにより、ページが更新されているかどうかを知るために追加のイベント処理 (window.onload など) を使用する必要がなくなります。準備ができて。 。

もう 1 つのオプションは、loadScript() 関数をページに直接埋め込むことです。これにより、http リクエストのオーバーヘッドを軽減できます。例:

コードをコピーします コードは次のとおりです:

1 <スクリプトタイプ="text/javascript"> 関数loadScript(url, callback){
var script = document.createElement ("script");
script.type = "text/javascript";

If (script.readyState){ //IE script.onreadystatechange = function(){
If (script.readyState == "ロード済み" || script.readyState == "complete"){
script.onreadystatechange = null; callback();
}
};
} else { //その他
script.onload = function(){
コールバック(); };
}
Script.src = URL
document.getElementsByTagName("head")[0].appendChild(script);
}

loadScript("the-rest.js", function(){
アプリケーション.init(); });




ページ初期化コードがダウンロードされたら、loadScript() 関数を使用して、ページに必要な追加関数をロードすることもできます。
一般的なツールとして、Yahoo! Search の Ryan Grove が LazyLoad ライブラリを作成しました (http://github.com/rgrove/lazyload/

を参照)。 LazyLoad は強力なloadScript() 関数です。 LazyLoad は縮小後わずか 1.5KB 程度です。使用例は次のとおりです。


コードをコピー

コードは次のとおりです:


<スクリプトタイプ="text/javascript">
LazyLoad.js("the-rest.js", function(){
Application.init();
});

概要

1. すべての

最新のダウンロード
詳細>
ウェブエフェクト
公式サイト
サイト素材
フロントエンドテンプレート