defer と async を使ってサイト高速化

<script> タグには defer または async 属性を指定できます。この2つは挙動が異なるため、うまく使い分けてサイトの表示を高速化しましょう。

<script> タグ

まず、defer や async を使わずに <script> タグで外部ファイルを読み込む場合について見ていきます。

<script src="script.js"></script>

このように記述した場合、HTMLパーサはこの部分に到達するとHTMLのパースを停止し、スクリプトファイルのダウンロード、および実行を行います。実行が終わると再びHTMLのパースに戻ります。

ただしこの挙動は document.write などを使ってHTMLを出力するようなスクリプトでない限り、不必要にHTMLのパースを止めてしまっています。

というわけで、「このスクリプトはHTMLのパースを止めてまで実行する必要はないですよ」ということをブラウザに明示するためにHTML4で生まれたのが defer 属性です。

defer

defer を使った場合は以下のように記述します。

<script src="script.js" defer></script>

このように記述した場合、HTMLパーサがこの部分に到達してもパースは停止せず、スクリプトの実行は後回しにされます。ただ、のちの実行に備えてパースと並行してスクリプトファイルのダウンロードは行われます。

そしてHTMLのパースが終了したのち、スクリプトの実行が行われます。

これによって不必要にHTMLのパースを停止せず、サイトを高速に表示することができるようになりました。

ただしこの挙動ではページ全体のHTMLパースが終了するまでスクリプトが実行されません。HTMLに関連する処理であればそれで良いですが、HTMLと独立して動作するスクリプトではそれでは遅いということがあります。

というわけで、もっと早くスクリプトを実行してほしいということをブラウザに明示するためにHTML5で生まれたのが async 属性です。

async

async を使った場合は以下のように記述します。

<script src="script.js" async></script>

このように記述した場合、defer と同じようにHTMLパーサがこの部分に到達してもパースは停止せず、並行してスクリプトのダウンロードが行われます。

defer と大きく異なるのが、スクリプトのダウンロードが完了次第、HTMLパーサを停止し、スクリプトを実行するという点です。これによってできるだけ早くスクリプトを実行することができるようになりました。

例えば Google アナリティクス用のスクリプトファイルなんかは async 属性をつけたほうが良いでしょう。defer 属性をつけるとHTMLパーサが終了するまで実行されないため正確なアクセス情報を取得できない可能性があります。async 属性をつけることでできるだけ早くスクリプトを実行し、正確なアクセス情報に近づけることができます。

defer の特徴

  • HTMLパーサを停止しない
  • HTMLのパースが終わり次第実行される
  • defer 属性をつけたスクリプトが全て実行されるまで DOMContentLoaded イベントは発火されない
  • 実行順序はHTMLの記述通り

async の特徴

  • スクリプトのダウンロード時にHTMLパーサを停止しない
  • スクリプトファイルのダウンロードが終わり次第、HTMlパーサを停止し、実行される
  • async 属性をつけたスクリプトが全て実行されるまで load イベントは発火されない
  • 実行順序は不定(ダウンロードが先に終わったものから実行される)

defer と async の使い分け

基本的に以下の使い分けでいいと思います。

  • 他のスクリプトファイルに依存される場合は defer(jQueryなど)
  • 他のスクリプトファイルに依存する場合も defer(jQueryプラグインなど)
  • DOM要素をいじる場合も defer(document.querySelectorとかを使う場合など)
  • 上記以外は async(Google アナリティクス用スクリプトなど)

defer と async の大きな違いの一つとして、実行順序が決まっているかどうかがあります。deferの場合、HTMLで先に書いたほうが先に実行されるようになっています。async の場合は実行順序は決まっていないため、依存関係にあるスクリプト同士を読み込む場合は defer を使ったほうが安全でしょう。

参考リンク

コメントを残す

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