Web

<script>タグのdefer/async属性について(その2:実例)

投稿日:2021年9月24日 更新日:

1. はじめに

先日書いた以下の記事の補足です。

Web Vitals

Webページ読み込み高速化に対する<script>タグのdefer/async属性について

2021.09.21

<script>タグの属性によって、JavaScript ファイルがどのように読み込まれるのか、以下の3パターンを実際のWebページを使って比べます。

  1. defer / async 属性を指定しない場合
  2. defer 属性を指定した場合
  3. async 属性を指定した場合

2. 方法

Chrome ブラウザのデベロッパーツール (DevTools) が持つ [Performance] パネルにて、読み込み処理を解析します。
以下のHTMLファイルを読み込ませます。60行のファイルです。

読み込む HTMLファイル

画像の中で示した、3つの <script>タグで JavaScript ファイルをそれぞれ読み込ませます。この <script>タグに defer / async 属性を指定します。

また、以下の記事も参考にしてください。

Chrome

Webページが読み込まれる際、HTMLは分割されてパースされます

2021.09.23

3. それぞれの読み込み処理を観察する

(1) defer / async 属性を指定しない場合

以下が解析結果の画面です。

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.jslazyload-css.js.js が実行されているのが分かります(この表示は紛らわしいですが、内部では JavaScriptコードの実行はパースをブロックしているはずです)。

※ 「-1」というのは「最後の行まで」を表していると思われます。

(2) defer 属性を指定した場合

以下が解析結果の画面です。

defer 属性を指定した場合

この場合は、JavaScript ファイルのダウンロードをしている間でも、パース処理が続行されています。1回目は 0から56行目、2回目は 57から59行目がパース対象となっており、ここで(一旦)パースは最後まで終わっています。

その後、JavaScript がダウンロードされ実行されています。

1つポイントとなるのは、<script>の記述の順番通りに、JavaScript が実行されている点です。

(3) async 属性を指定した場合

以下が解析結果の画面です。

async属性を指定した場合

この場合も、JavaScript ファイルのダウンロードをしている間に、パース処理は続行されています。1回目は 0から56行目、2回目は 57から59行目がパース対象となっており、ここで(一旦)パースは最後まで終わっています。

ただ defer と違い、JavaScript ファイルの実行順序は タグが記述されている順序通りにはなっていません。async属性の場合、実行順序は保障されていないのです。

また async 属性では、DOMContentLoaded (DCL) イベントの後に JavaScript が実行されることもあります(今回もそうなっています)。そのため、「async で読み込む JavaScript の中で定義されている関数などを利用するコード」を書く場所には注意が必要です。必要な JavaScript ファイルがまだ読み込まれていないために、エラーになることがあります。

4. まとめ

  1. Webページの読み込み&表示を遅くしないため、<script>タグには defer もしくは async 属性を指定することが望ましいです。
  2. 実行する順番が重要な JavaScript ファイルは、defer 属性を利用します。
    • jQuery などのライブラリはこれに該当すると思います。
  3. 画面上の要素を操作する処理を持つ JavaScript ファイルも、defer 属性を利用します。
  4. 実行順序に制約がなく、画面上の要素も操作しない処理しかない JavaScript ファイルであれば、async 属性を利用します。

📂-Web

執筆者:labo


comment

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です

関連記事

Web Vitals

highlight.js のハイライト処理を Web Workers で実行する

highlight.js のハイライト処理を Web Workers で実行する方法を紹介します。

Web Programming

Webプログラミングのための Web入門

この記事では、Webプログラミングで必要になる Webの知識をご紹介します。 目次1. インターネット2. インターネットを土台として存在するプロトコル3. Web とは?4. URL5. HTML2 …

Web

GitHub 上の Jupyter Notebooks を Binder で(実行可能な状態で)共有する

GitHub 上の Jupyter Notebooks を Binder で(実行可能な状態で)共有する方法について説明します。

DokuWiki

DokuWiki のプラグイン開発に関する情報

DokuWiki をなるべくスマートにカスタマイズしようとすると(設定変更以上のことをやりたい場合です)、テンプレートかプラグインを自作せざるを得ません。他の方法があまり用意されていないためです。 テ …

Chrome

Chrome の通信ログ(TCP/IPも含む)を記録する

Chrome の通信ログ(TCP/IPも含む)を記録する方法を紹介します。