JavaScript をいつ実行させるかは重要です
私が HTML を学習し始めたときには、<script>タグは</body>タグ(終了タグ)の直前に置くのと、<head>タグ内に置くのとで、特に解説なく疑問は感じていたかもしれませんがそういうものかと進んでました。
<script>タグにはいくつか属性をつけることが可能で、本記事ではasyncとdeferという属性について解説します。
まず結論から
JS の内容が HTML の表示と関係するならdeferを使おう!
HTML の表示と関係ないならasyncを使おう!
かなり乱暴に言うとこんな感じですかね...思いっきり間違っていたらすみません!!!
scirpt タグの配置について
ではまず冒頭のscriptタグをどこに配置するかについてですが、これについては<script>タグが、いつ実行されたいかをタグの配置で制御しているイメージですね。
ブラウザは基本的に HTML を上から順に実行・解析(パース)をするそうです。<head>タグ内に設置した<script>タグの中にdocument.getElementByIdなんてがっつり DOM を操作するメソッドが入っていたらどうなるのでしょうか?
まだ要素が存在しない状態で DOM を操作しようとすると、エラーが発生する可能性があります。
属性やら、要素が存在してから実行させる??何じゃそりゃという方は、結論の方法でとりあえず進んで大丈夫だと思います!多分...
属性すらよう分からん!って人は、ひとまず</body>(body 終了タグの)の直前に配置したら良いと思います!
DOMContentLoaded イベントについて
DOMContentLoadedとは?MDN から引用すると、
DOMContentLoaded イベントは、HTML の文書が完全に読み込まれ構文解析され、すべての遅延スクリプト(
<script defer src="…">および<script type="module">)がダウンロードされ、実行されたときに発生します。画像、サブフレーム、非同期スクリプトの読み込みの完了は待ちません。
だそうです。
これをつかって JS を実行させれば、DOM を操作するものについては安心ということですね。
どうやって全部使い分けるの?
1.ページ内の要素を操作するような重要な<script>に関しては、defer属性を付与して、<head>タグに配置する。
=>これにより、HTML のパースが行われた際にパースを妨げることなく非同期に読み込まれ、実行がパースが終わったタイミングで実行されるのでより効果的であるようです。(~~さらに、DOMContentLoadedイベントリッスンすることで、DOM が完全に構築された後にスクリプトが実行されるため、安心して要素を操作できます。~~そもそも</body>の直前に script を書けば、読み込まれる時点で要素が存在しているのでDOMcontentLoadedを書かなくても良いようです。)
例)ハンバーガーメニューやスライダーなど。
2.外部のリソース(Google Analytics や広告用のスクリプト)などはasyncを使う。これも<head>タグ内で特に問題なと思います。(</body>(body タグ終了直前でも問題はない気もします)
=>asyncタグは非同期に読み込まれ、HTML のパースを妨げませんが、読み込みが完了すると即座に実行され、その際にパースが一時中断されるようです。
という感じでしょうか。
もっとも、ページ内の要素に関わる重要なscriptに関してはDOMContentLoadedを使用すれば、HTML のパース後に実行されるので安心ではあります。
ChatGPT に聞いたところ、
DOMContentLoadedはdeferスクリプトの実行が完了した後に発生するため、スクリプト内で安全に DOM を操作することができます。
ということだそうです。(類似するものにloadイベントがありますが、こちらについてはまた今度書かせていただこうと思います)
色々と乱雑になってしまいましたが、自分への備忘録として残させていただきます。
文章を添削を GPT 様にお願いしたところ、軽い表現が多いですと指摘されてしまい落ち込み中笑