async または defer 属性のないスクリプト、およびインライン スクリプトは、ブラウザーがページの解析を続行する前に、すぐにフェッチされて実行されます - MDN
JavaScript のブロック特性。実際、ほとんどのブラウザはユーザー インターフェイス (UI) の更新と JavaScript の実行の両方に 1 つのプロセスを使用するため、JavaScript が長いほど、一度に 1 つのプロセスしか発生しません。実行に時間がかかるほど、ブラウザがユーザー入力に自由に応答できるようになるまでの時間が長くなります。 - Nicholas C. Zakas「高性能 JavaScript」上記で引用した 2 つの引用符の意味は、ブラウザが DOM を解析するときの意味です。ドキュメントが検出されると、スクリプト タグ (defer および async 属性なし) が検出されると、すぐにダウンロードされて実行されます。同時に、スクリプト コードの実行が完了するまで、ブラウザによるドキュメントの解析が停止します。このブロック動作は、ブラウザーの UI レンダリング、インタラクティブな動作などがシングルスレッド操作であるために発生します。他方、次のコードのように、スクリプト内のコードが後続のドキュメントの解析に影響を与える可能性があります。
そうですか
これは、ブロック機能はユーザー エクスペリエンスに深刻な影響を及ぼします。 以下にいくつかの最適化ソリューションを示します。
の。
依存関係に従ってスクリプトをファイルに配置してみてください
しかし、より良い方法は、次のノンブロッキング スクリプト (ノンブロッキング スクリプト) の方法です:
1. Deferred Script (遅延スクリプト)
スクリプト defer があります。この属性を持つスクリプトは、このスクリプトが DOM を変更しないことを示しているため、このスクリプトはドキュメント ツリーが完全に解析された後にトリガーされます (ドキュメントが解析された後に実行されます)。ただし、この属性はブラウザーによって所有されません。サポート。
2. 動的スクリプト要素
原則は、スクリプトを使用してスクリプト要素を作成し、スクリプトを動的に追加する必要がある URL を src に設定し、このスクリプトを DOM に追加することです。場合によっては、動的スクリプトのロード後に特定の操作を実行する必要があります。これには、スクリプトの onload イベントを通じてコールバック関数を追加する必要があります。次の実装コード:
html<script type="text/javascript"> document.write("The date is " + (new Date()).toDateString());</script>
場合によっては、動的にロードされたスクリプトをロードした順序で実行する必要がありますが、上記の実装では、ロードされたスクリプトがダウンロードの完了直後に実行されることは保証されません。定義した順序で実行されます。この問題を解決するのは難しいことではありません。次のコードを参照してください。
jsfunction loadJS(url, callback){ var script = document.createElement('script'); script.type = 'text/javascript'; if(script.readyState){ // 兼容IE的旧版本 script.onreadystatechange = function(){ if(script.readyState == 'loaded' || script.readyState == 'complete'){ script.onreadystatechange = null; callback(); } } } else{ script.onload = function(){ callback(); } } script.src = url; document.getElementsByTagName('head')[0].appendChild(script);}
動的に追加する必要があるスクリプトが多数ある場合は、このように記述するときにも問題が発生します。 LABjs などの既製のライブラリ
3. XMLHttpRequest スクリプト インジェクション (XHR 動的挿入)
他の方法と比較した利点の 1 つは、「遅延実行」できることです。つまり、JS コードが最初にダウンロードされ、実行されず、必要なときに (?) 実行できます (前の動的スクリプトは直後に実行されます)。ダウンロード)。実装コード:
jsloadJS('a.js', function(){ loadJS('b.js', function(){ loadJS('c.js', function(){ app.init(); }) })})
デメリットはクロスドメインリクエストができないこと
参考