script要素のJavaScript読み込みパターンについて
どうもoreoです。
今回は、script
要素のJavaScript読み込みパターンについて整理したいと思います。defer
属性やasync
属性を使用することで、JavaScriptの読み込みや実行を制御できるので、パフォーマンスを考える上では非常に重要ですね。
1 JavaScript読み込みパターン
JavaScriptの読み込みパターンは、WHATWGで以下のように分かりやすく纏められています。この図を基に解説していきます!
参考 : https://html.spec.whatwg.org/multipage/scripting.html
1-1 何も指定しない場合
この場合、HTMLパーサーがHTMLを先頭から順に解析し、script
要素に遭遇すると、解析を中断してJavaScriptの読み込みと実行を行います。JavaScriptの読み込みと実行の間は、解析処理が中断されるため、JavaScriptファイルが大きい場合、webページの表示に時間がかかります。
<script src="./test.js">
defer
属性を指定する場合
1-2 defer
属性を指定すると、HTML解析と並行してJavaScriptを読み込み、それらが終了した段階でJavaScriptが実行されます。defer
属性が付与されたscript
要素が複数存在する場合は、script
要素の記載順に実行されます。
defer
属性を使用する場合、src
属性がないと構文エラーとなります。
<script src="./test.js" defer>
async
属性を指定する場合
1-3 aync
属性を指定すると、HTML解析と並行してJavaScriptを読み込み、JavaScriptの読み込みが終了した段階でHTML解析を中断して、JavaScriptの実行を行い、実行後にHTML解析が再開されます。async
属性が付与されたscript
要素が複数存在する場合は、defer
属性とは異なり、実行順はscript
要素の記載順にはなりません。
aync
属もdefer
属性と同様に、src
属性がないと構文エラーとなります。また、defer
属性とaync
属性を同時に指定すると、aync
属性の挙動となります。
<script src="./test.js" async>
type
属性をmodule
に指定する場合
1-4 type
属性の値としてmoduleを指定すると、リソースはモジュールとして読み込まれるようになります(モジュールスクリプトと呼びます)。この場合、defer
属性と同じように、HTML解析と並行してJavaScriptを読み込み、それらの読み込みが終了した段階でJavaScriptが実行されます。
<script type="module" src="./test.js">
また、モジュールスクリプトにasync
属性を指定した場合は、「1-3 async
属性を指定する場合」と同じ挙動となります。
<script type="module" src="./test.js" async>
2 最後に
どの読み込み方を採用するかはケースバイケースだと思いますので、その都度判断できるよに、各々の違いをしっかり理解しておきたいですね。
3 参考
Discussion
非常にわかりやすい記事ありがとうございます!
nitpickですが、
**defer属性と同じ**ように
のところ、太字にしようとしてtypoしてるみたいですikutaさん!コメント&ご指摘ありがとうございました。修正させていただきました!!