目次
1. はじめに
先日書いた以下の記事の補足です。
<script>
タグの属性によって、JavaScript ファイルがどのように読み込まれるのか、以下の3パターンを実際のWebページを使って比べます。
- defer / async 属性を指定しない場合
- defer 属性を指定した場合
- async 属性を指定した場合
2. 方法
Chrome ブラウザのデベロッパーツール (DevTools) が持つ [Performance] パネルにて、読み込み処理を解析します。
以下のHTMLファイルを読み込ませます。60行のファイルです。
画像の中で示した、3つの <script>
タグで JavaScript ファイルをそれぞれ読み込ませます。この <script>
タグに defer / async 属性を指定します。
また、以下の記事も参考にしてください。
3. それぞれの読み込み処理を観察する
(1) defer / async 属性を指定しない場合
以下が解析結果の画面です。
画像の中で [0…48] とあるのは、HTMLファイルの0行目から48行目に対するパース処理です。以前書いた記事でも説明しましたが、1つのHTMLファイルを上からいくつかに分割して、上の部分からパースされます。それぞれのパース処理の間で別の処理が行なわれることもあります。
今回の場合、1回目のパース [0…48] 対象行の直後に、タグがあるため、ここで一旦パースは終わり、<script>
タグで指定された JavaScript ファイルを取得する処理が開始されます。残りのHTMLの行に対するパース処理は後回しにされます。このような動作になるのは、「defer / async 属性が指定されていない <script>
タグの場合、JavaScriptファイルのダウンロードと実行処理は、パース処理をブロックする」という動作が原因です。
そして、jquery-3.6.0.min.js
の実行が終わった後に、残りのHTMLに対するパースが再開されています。また、その2回目のパース [49…-1] の下の部分で、highlight.min.js
と lazyload-css.js.js
が実行されているのが分かります(この表示は紛らわしいですが、内部では JavaScriptコードの実行はパースをブロックしているはずです)。
※ 「-1」というのは「最後の行まで」を表していると思われます。
(2) defer 属性を指定した場合
以下が解析結果の画面です。
この場合は、JavaScript ファイルのダウンロードをしている間でも、パース処理が続行されています。1回目は 0から56行目、2回目は 57から59行目がパース対象となっており、ここで(一旦)パースは最後まで終わっています。
その後、JavaScript がダウンロードされ実行されています。
1つポイントとなるのは、<script>
の記述の順番通りに、JavaScript が実行されている点です。
(3) async 属性を指定した場合
以下が解析結果の画面です。
この場合も、JavaScript ファイルのダウンロードをしている間に、パース処理は続行されています。1回目は 0から56行目、2回目は 57から59行目がパース対象となっており、ここで(一旦)パースは最後まで終わっています。
ただ defer と違い、JavaScript ファイルの実行順序は タグが記述されている順序通りにはなっていません。async属性の場合、実行順序は保障されていないのです。
また async 属性では、DOMContentLoaded (DCL) イベントの後に JavaScript が実行されることもあります(今回もそうなっています)。そのため、「async で読み込む JavaScript の中で定義されている関数などを利用するコード」を書く場所には注意が必要です。必要な JavaScript ファイルがまだ読み込まれていないために、エラーになることがあります。
4. まとめ
- Webページの読み込み&表示を遅くしないため、
<script>
タグには defer もしくは async 属性を指定することが望ましいです。 - 実行する順番が重要な JavaScript ファイルは、defer 属性を利用します。
- jQuery などのライブラリはこれに該当すると思います。
- 画面上の要素を操作する処理を持つ JavaScript ファイルも、defer 属性を利用します。
- 実行順序に制約がなく、画面上の要素も操作しない処理しかない JavaScript ファイルであれば、async 属性を利用します。