こんにちは。
今回はJavaScript(以下JS)の「defer属性」と「async属性」について解説します。
これらの属性を使うことでページの表示速度をあげることが出来るのでぜひ理解しましょう。
早速、一覧の図をみてみましょう。(最後にまたお見せします)

①ノーマル状態をヘッドに入れ込むとどうなる?
HAED内にスクリプトを読み込むとどうなるか?
つまり
<head>
<script src="script.js"></script>
</head>
の状態です。
そうすると下図のような読み込み順になります。

この時、HTMLの一番上からソースの解析が始まり、DOMツリーを構成します。
そして、<script>を見つけます。(ミドリのブロックですね)
<script>の読み取りを始め、次に実行を行います。(黄色のブロックですね)
しかしこの間HTML解析は一旦止まってしまいます。
<script>の実行が完了したら、残りのHTML解析が再開されます。
もちろんこの記述は理想的ではないです。
スクリプト読み込み中はブラウザは何もせずに止まっている状態だからです。
さらにDOM読み込みが未完の状態でスクリプトを実行しているからそれも良くないですね。
絶対にヘッド内に<script src=”script.js”></script>と記述するのはやめましょう。
こういう理由があるから<script>はBODYの末に記述します。
そうすることで下図のような読み込み順になります。

こうすることによってHTMLの読み込みが一時停止することなく進みます。
今までなんとなくBODY末に書いていたかと思いますがこういう理由があったんですね。
じゃあ<script>はBODY末に記述するのが一番いいのか??
実はそういうわけではないのです。
理由はスクリプトはHTMLの解析途中でも読み込むことが出来るからです。
そしてそれがページの読み込み速度を改善させるのです。
③ async属性
<head>
<script async src="script.js"></script>
</head>
通常の記述(<script src=”script.js”></script>)とは違い、
<script async src=”script.js”></script>とasync属性を追記することで、
HTML解析と同時にスクリプトの読み込みが行われます。
下図をみてください。

ただ、スクリプトの実行時にはHTML解析は一旦止まってしまいます。
しかし通常のBODY末に記述するよりもページのローディング時間は早くなります。
DOMの読み込みが完了していない状態でスクリプトが実行されるのでコードの書き方によってはエラーが出てしまいます。
またasync属性の特徴として、複数のJSファイルを読み込む場合はダウンロードが早く完了したものから実行されてしまいます。
なのでライブラリーを先に読み込ませないといけない時に自分のスクリプトが先に読み込みが完了してしまうと、ライブラリーを実行できなという問題が起きてしまいます。
GAタグや広告タグなどは単体で動く(自作のスクリプトとは関わらない)のでasync属性を追記しておいた方がいいです。(多分すでに入っていると思います。)
④ defer属性
<head>
<script defer src="script.js"></script>
</head>
まずは下図をみてください。

<script defer src=”script.js”></script>と記述するdefer属性はasync属性と同様にスクリプトの読み取りはHTML解析と同時に行われますがスクリプトの実行はHTML解析が終わってから行われます。
したがってHTML解析は一度も停止しません。
またdefer属性は上から順番に読み込みをしていくので、ライブラリーを使うことで読み込みの順番を気にしないといけない時はdefer属性の追記をしましょう。
async属性とdefer属性はBODY末に入れる意味はないです。
通常実装であればdefer属性を適応するのが一番良さそうです。
まとめ
最後にもう一度全体図をみましょう。

<script>をBODY末に記述するよりも、async属性とdefer属性を使い分けることでページ読み込み速度をあげることができます。
①、②よりも③、④の棒グラフが短いのがわかります。
つまりページの読み込みが時間が短くなっているのです。
defer属性を使って上から読み込ませたい順に<script>をヘッド内に記述すると良さそうです。
GAタグや広告タグはasync属性の方が効率的に読み込ませることが出来ます。
今回は以上となります。
皆さんのJSの理解に繋がっていれば幸いです。
では!
▼▼あわせて読みたいの記事▼▼
【JS】イベントリスナー’ DOMContentLoaded ‘と’ load ‘の違いを解説