ホームページ > ウェブフロントエンド > jsチュートリアル > スクリプトタグの defer 属性と async 属性の簡単な分析

スクリプトタグの defer 属性と async 属性の簡単な分析

高洛峰
リリース: 2016-12-03 13:51:06
オリジナル
1106 人が閲覧しました

1. はじめに

私が見た先輩のコードは以下の通りです

<script src="#link("xxxx/xx/home/home.js")" type="text/javascript" async defer></script>
ログイン後にコピー

予想外に、先輩ドライバーの何らかのブラックテクノロジーに違いないと思いました。この 2 つが一緒になると、魔法のような化学反応が起きるのではないでしょうか。そこで私は敬虔な心で本や資料をざっとめくり、まずそれぞれの定義を確認しました。

次に、いくつかの調査を行います

まず、async と defer の定義を見てみましょう。Red Book Telescope を開くと、次のように紹介されています

2.1 defer

この属性の目的は、スクリプトはページの構造には影響しません。つまり、スクリプトは、実行前にページ全体が解析されるまで遅延されます。したがって、<script> 要素に defer 属性を設定することは、ブラウザにすぐにダウンロードするが実行を遅らせるように指示することと同じです。 </p><p> HTML5 仕様では、スクリプトは出現順に実行する必要があるため、最初の遅延スクリプトは 2 番目の遅延スクリプトの前に実行され、これら 2 つのスクリプトは DOMContentLoaded イベントの前に実行されます。実際には、遅延スクリプトは必ずしも順番に実行されるわけではなく、DOMContentLoad 時間がトリガーされる前に実行される必要もないため、遅延スクリプトは 1 つだけ含めることをお勧めします。 </p><p>2.2 async</p><p> この属性は defer に似ており、処理スクリプトの動作を変更するために使用されます。また、遅延と同様に、async は外部スクリプト ファイルに対してのみ機能し、ブラウザーにファイルをすぐにダウンロードするように指示します。ただし、遅延とは異なり、非同期とマークされたスクリプトは、その順序で実行されることが保証されません。 </p><p> 2 番目のスクリプト ファイルは、最初のスクリプト ファイルより前に実行される場合があります。したがって、この 2 つが相互に依存していないことを確認することが重要です。 async 属性を指定する目的は、ページが 2 つのスクリプトのダウンロードと実行を待機して、ページの他のコンテンツが非同期で読み込まれるのを防ぐことです。 </p><p>要約すると、これら 2 つの属性によりスクリプト タグが非同期で読み込まれますが、実行のタイミングが異なります。セグメントフォールトの回答からの画像の引用</p><p><img src="https://img.php.cn//upload/image/407/696/562/1480744109367059.jpg" title="1480744109367059.jpg" alt="スクリプトタグの defer 属性と async 属性の簡単な分析"/></p><p> 青い線はネットワーク読み取りを表し、赤い線は実行時間を表し、両方ともスクリプト用です。緑の線は HTML 解析を表します。 </p><p>つまり、async は順不同ですが、defer は順番に実行されます。これにより、他のスクリプトに依存しない Baidu Analytics や Google Analytics などのライブラリには async がより適していると判断されます。この図から、通常の <script> タグの読み込みと解析が同期していることがわかります。これが、<body> の最後に <script> を記述する理由です。まず、リソースの読み込みによって発生する長時間の白画面を防ぐため、もう 1 つの理由は、js が DOM 操作を実行する可能性があるため、すべての DOM がレンダリングされた後に実行する必要があることです。 </p><p>2.3って本当ですか? </p><p>ただし、この図 (Baidu で見つかったほぼ唯一の答え) は厳密なものではなく、これは単なる標準的な状況であり、ほとんどのブラウザーは実装時に最適化を行います。 </p><p>Chrome がどのように動作するかを見てみましょう</p><p>「WebKit Technology Insider」: </p><p> 1. ユーザーが Web ページの URL を入力すると、WebKit はそのリソース ローダーを呼び出して、その URL に対応する Web ページをロードします。 <br/></p><p> 2. ローダーはネットワーク モジュールに依存して接続を確立し、リクエストを送信し、応答を受信します。 <br/></p><p> 3. WebKit はさまざまな Web ページまたはリソースからデータを受け取りますが、その一部は同期または非同期で取得される場合があります。 <br/></p><p> 4. Web ページは HTML インタプリタに渡され、一連の単語 (トークン) に変換されます。 <br/></p><p> 5. インタプリタは単語に基づいてノード (Node) を構築し、DOM ツリーを形成します。 <br/></p><p> 6. ノードが JavaScript コードの場合、JavaScript エンジンを呼び出して解釈して実行します。 <br/></p><p> 7. JavaScript コードは DOM ツリーの構造を変更する場合があります。 <br/></p><p> 8. ノードが画像、CSS、ビデオなどの他のリソースに依存する必要がある場合は、リソースローダーを呼び出してそれらをロードしますが、それらは非同期であり、現在の DOM ツリーの継続的な作成を妨げません。 ; JavaScript リソース URL の場合 (非同期モードをマークしない場合)、DOM ツリーの作成を続行する前に、JavaScript リソースが JavaScript エンジンによってロードされて実行されるまで、現在の DOM ツリーの作成を停止する必要があります。 <br/></p><p>したがって、一般的に言えば、Chrome ブラウザは最初に HTML ドキュメントをリクエストし、次にその中のさまざまなリソースに対応するリソース ローダーを呼び出して非同期ネットワーク リクエストを行い、同時に < に遭遇するまで DOM レンダリングを実行します。 script> タグ この時点で、メイン プロセスはレンダリングを停止し、リソースがロードされるのを待ってから、V8 エンジンを呼び出して js を解析し、DOM 解析を続行します。私の理解では、async 属性を追加することは、独立してロードして実行するために別のプロセスを開くことと同等であり、defer は <body> の最後に <script> を配置するのと同じ効果があります。 </p><p>3. 実験1<br/></p><p>3.1デモ</p><p>上記の結論を検証するために、テストしてみましょう</p><div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:html;toolbar:false">&lt;!DOCTYPE html&gt; &lt;html lang=&quot;en&quot;&gt; &lt;head&gt; &lt;meta charset=&quot;UTF-8&quot;&gt; &lt;title&gt;Document&lt;/title&gt; &lt;link href=&quot;http://libs.baidu.com/bootstrap/3.0.3/css/bootstrap.css&quot; rel=&quot;stylesheet&quot;&gt; &lt;link href=&quot;http://cdn.staticfile.org/foundation/6.0.1/css/foundation.css&quot; rel=&quot;stylesheet&quot;&gt; &lt;script src=&quot;http://lib.sinaapp.com/js/angular.js/angular-1.2.19/angular.js&quot;&gt;&lt;/script&gt; &lt;script src=&quot;http://libs.baidu.com/backbone/0.9.2/backbone.js&quot;&gt;&lt;/script&gt; &lt;script src=&quot;http://libs.baidu.com/jquery/2.0.0/jquery.js&quot;&gt;&lt;/script&gt; &lt;/head&gt; &lt;body&gt; ul&gt;li{这是第$个节点}*1000 &lt;/body&gt; &lt;/html&gt;</pre><div class="contentsignin">ログイン後にコピー</div></div><p> </p> <p></p> <p>さまざまな CDN から 2 つの CSS と 3 つの JS を引用し、本文に 1000 li を作成する簡単なデモ。 Chrome のタイムラインを使用して、外部参照リソースの場所を調整し、関連する属性を追加して検証します。 </p> <p>3.2 </p>に配置されます<p><img src="https://img.php.cn//upload/image/696/384/898/1480744154246530.jpg" title="1480744154246530.jpg" alt="スクリプトタグの defer 属性と async 属性の簡単な分析"></p> <p>リソースを非同期で読み込みますが、</p>のレンダリングをブロックし、白い画面が表示されます<p>3.3 の下部に配置されます。 </p> <p> <img src="https://img.php.cn//upload/image/639/130/331/1480744171245752.jpg" title="1480744171245752.jpg" alt="スクリプトタグの defer 属性と async 属性の簡単な分析"></p> <p> リソースを非同期でロードし、</p> のコンテンツがレンダリングされてロードされるのを待ち、JS を順番に実行します<p>3.3 </p> ヘッダーに配置して async を使用します<p> <img src="https://img.php.cn//upload/image/392/809/508/1480744186346776.jpg" title="1480744186346776.jpg" alt="スクリプトタグの defer 属性と async 属性の簡単な分析"></p> <p> リソースを非同期でロードし、JS リソースは順番ではなく完了後にすぐに実行されます</p> <p>3.4 </p> に配置して defer を使用します<p><img src="https://img.php.cn//upload/image/414/954/733/1480744198930605.jpg" title="1480744198930605.jpg" alt="スクリプトタグの defer 属性と async 属性の簡単な分析"></p> <p>リソースを非同期でロードし、DOM がレンダリングされた後に JS を順番に実行します </p> <p>3.5 それを </p> ヘッドに配置し、async と defer を同時に使用します<p><img src="https://img.php.cn//upload/image/312/914/529/1480744214244130.jpg" title="1480744214244130.jpg" alt="スクリプトタグの defer 属性と async 属性の簡単な分析"></p> <p> パフォーマンスは async と一致します。心を開いて、これら 2 つの属性の位置を交換して、オーバーレイ効果があるかどうかを確認しました。結果は一貫していることがわかりました。</p> <p> 要約すると、Webkit エンジンでは、依然として推奨される方法です。 Baidu Google Analytics や Bulianzi などの独立したライブラリを使用する必要がある場合は、<script> を <head> に記述します。 ; ヘッダーでは defer 属性を使用できます。互換性とは何ですか? </script>

caniuse では、IE

async 属性が指定されている場合でも defer 属性を指定すると、遅延のみをサポートする (非同期ではなく) レガシー Web ブラウザーがデフォルトの同期ブロック動作ではなく遅延動作にフォールバックすることがあります。

5. 結論

実際、最も安全な方法は、

の下部に <script> を記述することです。互換性の問題、白い画面の問題、実行順序の問題は発生しません。現時点では、Firefox と IE のレンダリング メカニズムのみを研究しており、画像、CSS、その他の外部リソースのレンダリングについては引き続き研究する必要があります。研究される。 <p><br/></script>
関連ラベル:
ソース:php.cn
このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。
最新の問題
人気のチュートリアル
詳細>
最新のダウンロード
詳細>
ウェブエフェクト
公式サイト
サイト素材
フロントエンドテンプレート