目次
1. はじめに
「Webページの読み込み高速化」という観点から、「<script>
タグの defer / async 属性」について書いてみます。
2. <script>タグに defer / async 属性を付けた場合のブラウザの動作
まず、HTMLの仕様である HTML Living Standard から画像を引用します。
この画像では、以下の3種類の動作についての違いについて説明されています。
- ただの
<script>
タグ - defer 属性付きの
<script>
タグ - async 属性付きの
<script>
タグ
ここで図示されている違いを言葉で説明すると以下になります。
(1) ただの <script>タグ
- HTMLのパース(*1)を止める
- JavaScriptファイルをダウンロードする
- JavaScriptコードを実行する
- JavaScriptコードの実行が終わったら、HTMLのパースを再開します。
(*1) HTMLを読み込んでDOMツリーを構築する処理
(2) defer 属性付きの<script>タグ
- HTMLのパースを止めず、並列に JavaScriptファイルをダウンロードする
- HTMLのパースが完了したら、JavaScriptコードを実行する (DOMContentLoadedイベントをブロックする)
※ defer 属性付きの <script>タグが複数あった場合、記述されている順番で実行されます。
(3) async 属性付きの <script>タグ
- HTMLのパースを止めず、並列に JavaScriptファイルをダウンロードする
- ダウンロードが終わったら、HTMLのパースを止めて、JavaScriptコードを実行する。(私の観察では、DOMContentLoaded の前までには実行されます)
- JavaScriptコードの実行が完了したら、HTMLのパースを再開する。
※ async 属性付きの <script>
タグが複数あった場合、実行される順番は決まっていません。
3. defer / async 属性関連のポイント
以上の動作を踏まえて defer / async 属性に関連するポイントをまとめます。
(1) defer / async なしの場合、HTMLのパースを止めて JavaScript ファイルをダウンロードするので、そのページの読み込み処理が遅くなる。そのため、できるだけどちらかを付けたほうが良い。
(2) JavaScript の実行の順番が重要である場合は、defer 属性を使う。
(3) 画面上の要素を操作する処理を行う JavaScript には defer 属性を使う。
(4) jQuery のような重めのJavaScriptライブラリは、他から依存されているはずなので、defer 属性を利用すると良い。
(5) 画面上の要素を操作しない処理で、実行の順番が問題にならない JavaScript には、async 属性を使う。但し、すぐに実行されることで読み込み&表示処理が遅くなっているのなら、defer 属性に変える。
※ 実際のページはいろいろな要素が関連していることがあるので、解析して最適解を探るのがよい。
以下は補足情報です。defer / async 属性と関連が薄い項目もありますが、重要なので書いておきます。
(6) JavaScriptファイルのダウンロードや、JavaScriptコードの実行処理を短時間で終わらせるために、ページ単位で必要最低限の JavaScript だけを読み込むようにWebサイトを作成する。
※ JavaScript を分割して、ページ毎に必要なものだけを読み込ませる。そして、ページ毎の JavaScript を圧縮 + キャッシュさせる。
※ JavaScriptファイルの動的インポートを利用する。
(7) WordPress などで JavaScript 圧縮プラグインを使っている場合は、出力される <script>
タグにどんな属性が指定されているか注意する(圧縮対象になった元の <script>
タグにどんな属性が指定されていたかについても注意する)。
(8) あまりに処理が重い JavaScript ならば、ページ上でユーザーが何らかの操作を行ったタイミング(イベント)で実行させることも検討する。
だいたいこのくらいでしょうか。
4. おわりに
「<script>
タグに defer / async 属性を指定する」というのは、パフォーマンス測定ツールの実行結果に割と大きく影響する項目の1つになっています。
使用している JavaScript コードを分割したり、依存関係を完璧にコントロールするのはかなり骨の折れる作業ですが、依存関係に問題のなさそうな <script> タグに defer / async 属性を指定するというのは、Webページの高速化において、簡単且つ必須な作業であると言えます。