Code Tips‎ > ‎

SCRIPT要素のdefer, async属性



通常、SCRIPT要素は以下のように書きますが、
<script type="text/JavaScript" src="./script.js"></script> …(1)

JavaScriptファイルの読み込みに時間がかかる場合には
<script type="text/JavaScript" src="./script.js" defer></script> …(2)
<script type="text/JavaScript" src="./script.js" async></script> …(3)
のどちらかにするといいですよ、という話です。


ブラウザはHTML文書を先頭から順に読み込み解釈していき、読み込んだ部分を並行して画面に描画していきます。そしてSCRIPT要素に到達したとき、(1)の書き方の場合、JavaScriptの読み込み+実行(登録)が完了するまで画面の描画を停止します。

ですので、JavaScriptファイルの読み込みが遅い場合には、HTMLの画面描画自体が遅れてしまいます。これを防ぐために新しく追加された属性です。実装が最も遅れていたメジャーブラウザはIEでしたが、IEもIE10からサポートしたので、現在ではメジャーブラウザの最新版ではすべてでサポートされています(詳しいサポート状況についてはMDNのページを参照してください)


属性の有無による違いを簡単にまとめました。
サンプルNo. (1) (2) (3)
属性 なし defer async
画面描画の中断 する しない しない
JavaScriptファイルの
実行タイミング
画面描画中に
JavaScriptファイル
呼び出し順
画面描画後でかつ
JavaScriptファイル
呼び出し順
画面描画でかつ
JavaScriptファイル
読み込み完了順

最も大きな問題は、画面描画を中断するかしないかです。属性なしの場合だけ中断します。JavaScriptファイルの読み込み速度が特に問題になっていない場合にはあえて指定する必要はありませんが、そうでない場合はdeferかasyncのどちらかを指定することになります。

deferとasyncの違いは、複数のJavaScriptファイルを読み込むときの実行順です。deferは記述順に実行しますが、asyncは読み込みが完了した順に実行します。※JavaScriptファイルが1つの場合には違いはありません。

複数のファイルに依存関係がある場合には、deferを指定しなければなりません。例えばjQueryのライブラリを読み込み、jQueryを利用する処理も外部ファイルにしている場合、jQueryの読み込みを前に書いたとしても、jQueryの読み込みに時間がかかった場合には、「$ is not defined」とのエラーが出てしまいます。

一方、JavaScriptファイルの依存がなく、できるだけ全体の処理を早く終わらせたい場合にはasyncを指定することになります。asyncを指定すれば実行する準備が整った順に実行されます(とはいえ、実際に発生する処理時間はさほど変わらないと思いますが…)


というように、それぞれ違いがあり使い分けるべきではあるのですが、あまり深く考えず「とりあえずdeferを指定する」でも十分かと思います。



参考:script 要素 - HTML | MDN

2016/07/18