スクリプトを動的にロードしたり、またはとしてマークしたりしていない場合defer
、async
スクリプトはページで検出された順序でロードされます。外部スクリプトであるかインラインスクリプトであるかは関係ありません。ページで検出された順序で実行されます。外部スクリプトの後にあるインラインスクリプトは、それらの前にあるすべての外部スクリプトがロードされて実行されるまで保持されます。
非同期スクリプト(非同期として指定されている方法に関係なく)は、予測できない順序でロードおよび実行されます。ブラウザはそれらを並行してロードし、好きな順序で自由に実行できます。
複数の非同期のものの間に予測可能な順序はありません。予測可能な順序が必要な場合は、非同期スクリプトからのロード通知を登録し、適切なものがロードされたときにjavascript呼び出しを手動でシーケンスすることにより、コード化する必要があります。
スクリプトタグが動的に挿入される場合、実行順序がどのように動作するかはブラウザによって異なります。このリファレンス記事でFirefoxの動作を確認できます。一言で言えば、Firefoxの新しいバージョンでは、スクリプトタグが別の方法で設定されていない限り、動的に追加されたスクリプトタグがデフォルトで非同期になります。
のスクリプトタグasync
は、ロードされるとすぐに実行される場合があります。実際、ブラウザはパーサーを他の処理から一時停止して、そのスクリプトを実行する場合があります。したがって、実際にはほとんどいつでも実行できます。スクリプトがキャッシュされている場合、ほとんどすぐに実行される可能性があります。スクリプトのロードに時間がかかる場合は、パーサーの実行後に実行される可能性があります。覚えておくべきことの1つasync
は、いつでも実行でき、その時間は予測できないということです。
のスクリプトタグdefer
は、パーサー全体が完了するまで待機してから、でマークされたすべてのスクリプトを検出さdefer
れた順序で実行します。これにより、相互に依存する複数のスクリプトをとしてマークすることができますdefer
。これらはすべて、ドキュメントパーサーが完了するまで延期されますが、依存関係を維持しながら、検出された順序で実行されます。defer
スクリプトがキューにドロップされ、パーサーが完了した後に処理されるように思います。技術的には、ブラウザはいつでもバックグラウンドでスクリプトをダウンロードしている可能性がありますが、パーサーがページの解析とマークされていないインラインスクリプトの解析と実行を完了するまで、パーサーを実行またはブロックしませdefer
んasync
。
その記事からの引用は次のとおりです。
スクリプトが挿入されたスクリプトは、IEとWebKitでは非同期に実行されますが、Operaと4.0より前のFirefoxでは同期的に実行されます。
HTML5仕様の関連部分(新しい準拠ブラウザー用)はここにあります。非同期動作についてはたくさん書かれています。明らかに、この仕様は、動作を判断するためにテストする必要がある古いブラウザ(または不適合なブラウザ)には適用されません。
HTML5仕様からの引用:
次に、状況を説明する次のオプションの最初のオプションに従う必要があります。
要素にsrc属性があり、要素にdefer属性があり、要素に「パーサー挿入」のフラグが付けられていて、要素に非同期属性がない場合要素は
、のリストの最後に追加する必要があります。要素を作成したパーサーのドキュメントに関連付けられたドキュメントの解析が終了したときに実行されるスクリプト。
フェッチアルゴリズムが完了した後にネットワークタスクソースがタスクキューに配置するタスクは、要素の「パーサー実行の準備ができました」フラグを設定する必要があります。パーサーはスクリプトの実行を処理します。
要素にsrc属性があり、要素に「パーサー挿入」のフラグが付けられていて、要素に非同期属性がない場合
要素は、要素を作成したパーサーのドキュメントの保留中の解析ブロックスクリプトです。(このようなスクリプトは、ドキュメントごとに一度に1つしか存在できません。)
フェッチアルゴリズムが完了した後にネットワークタスクソースがタスクキューに配置するタスクは、要素の「パーサー実行の準備ができました」フラグを設定する必要があります。パーサーはスクリプトの実行を処理します。
要素にsrc属性がなく、要素に「パーサー挿入」のフラグが設定されていて、スクリプト要素を作成したHTMLパーサーまたはXMLパーサーのドキュメントに、スクリプトをブロックしているスタイルシートがある場合要素は保留中の解析-要素を作成したパーサーのドキュメントのブロックスクリプト。(このようなスクリプトは、ドキュメントごとに一度に1つしか存在できません。)
要素の「パーサー実行の準備ができました」フラグを設定します。パーサーはスクリプトの実行を処理します。
要素にsrc属性があり、async属性がなく、「force-async」フラグが設定されていない場合要素は、関連付けられたできるだけ早く順番に実行されるスクリプトのリストの最後に追加する必要がありますスクリプトアルゴリズムの準備が開始されたときのスクリプト要素のドキュメントを使用します。
フェッチアルゴリズムが完了した後にネットワークタスクソースがタスクキューに配置するタスクは、次の手順を実行する必要があります。
要素が、上記で追加されたスクリプトのリストの最初の要素ではない場合は、要素を準備完了としてマークしますが、スクリプトをまだ実行せずにこれらの手順を中止します。
実行:このスクリプトリストの最初のスクリプト要素に対応するスクリプトブロックを実行します。このスクリプトは、できるだけ早く順番に実行されます。
このスクリプトのリストから、できるだけ早く順番に実行される最初の要素を削除します。
できるだけ早く順番に実行されるこのスクリプトのリストがまだ空でなく、最初のエントリがすでに準備完了としてマークされている場合は、実行というラベルの付いたステップに戻ります。
要素にsrc属性がある場合、スクリプトアルゴリズムの準備が開始されたときに、スクリプト要素のドキュメントをできるだけ早く実行するスクリプトのセットに要素を追加する必要があります。
フェッチアルゴリズムが完了した後にネットワークタスクソースがタスクキューに配置するタスクは、スクリプトブロックを実行してから、できるだけ早く実行されるスクリプトのセットから要素を削除する必要があります。
それ以外の場合、他のスクリプトがすでに実行されている場合でも、ユーザーエージェントはスクリプトブロックをすぐに実行する必要があります。
Javascriptモジュールスクリプトはtype="module"
どうですか?
Javascriptは、次のような構文でモジュールの読み込みをサポートするようになりました。
<script type="module">
import {addTextToBody} from './utils.mjs';
addTextToBody('Modules are pretty cool.');
</script>
または、src
属性付き:
<script type="module" src="http://somedomain.com/somescript.mjs">
</script>
のすべてのスクリプトにtype="module"
は、自動的にdefer
属性が与えられます。これにより、ページの他のロードと並行して(インラインでない場合)それらがダウンロードされ、順番に実行されますが、パーサーが完了した後です。
モジュールスクリプトには、パーサーが完了するまで待機せず、他のスクリプトに対して特定の順序でスクリプトasync
を実行するのを待たずに、できるだけ早くインラインモジュールスクリプトを実行する属性を指定することもできます。async
この記事のモジュールスクリプトを含む、スクリプトのさまざまな組み合わせのフェッチと実行を示す非常に便利なタイムラインチャートがあります:JavascriptModuleLoading。