defer属性を付与するのはなぜか
defer(ディファー)とは、HTMLの <script> タグに使う属性で、スクリプトの実行タイミングを「HTMLの解析・表示がすべて完了した後」に遅らせるためのものです。
(deferとは、英語で「延期する」「先延ばしにする」という意味。)
通常、<script> だけだとHTMLの読み込みは中断されて即JavaScriptが実行されますが、defer属性を付けるとHTMLのパース・DOM構築が完了してから、そのスクリプトが順次実行されます。
複数の <script src="..." defer> タグがある場合は、記述順に実行されます。
ページ表示速度を落とさずDOMContentLoaded直前に実行させたいコードに便利です。
DOMContentLoadedとは
HTML文書が完全に読み込まれ、構文解析(パース)が完了してDOMツリーが構築された時点で発火するJavaScriptのイベント。
簡単に言うと、「HTMLの骨組み(DOMの構造)が完成したよ!」というタイミング。
属性値は不要で、<script src="...js" defer></script>と書くのが一般的です。
注意: deferは外部スクリプト専用(src属性つきのときのみ有効)です。
xml <script src="app.js" defer></script>
このようにすることで、スクリプトによる描画の停止を避けつつ、HTML全文をパースした上でJSを順序通り実行できるようになります。
パースとDOMで行われる処理と2つの違い
HTMLの「パース」とは、ブラウザがHTMLファイルを1文字ずつ読み取り、意味のある単位(トークン)に分解し、解釈していく処理です。
パース(parse)は日本語で「構文解析する」「解析する」という意味で使われます。
IT分野では、文字列やコードを文法や構造に従って分析し、意味のある部品(トークン)に分解する処理のことを指します。
そして、「DOM構築」とは、そのパース結果をもとに、HTML要素の階層構造=DOM(Document Object Model)ツリーを生成することを指します。
HTMLパース(解析):
HTMLパーサーがHTML文字列をトークンごと(タグ、テキスト、コメントなど)に分割し(字句解析)、そのトークンから階層構造(親子関係・入れ子)を認識していく(構文解析)。
これによって、HTMLコードがどのような構造を持っているかコンピュータが理解できるようになります。
DOM構築:
パースされた情報をもとに、DOMツリーという木構造のデータが作られます。
このツリー上の各ノード(枝)は、HTMLの各要素(<html>, <head>, <body>, など)を示し、ブラウザやJavaScriptはこのツリーを使ってページを操作・表示します。
例として、以下のようなHTMLがあるとすると
<html> <body> <h1>Hello</h1> <p>World</p> </body> </html>
DOM構築後には
最上位に「Documentノード」
その下に「html」ノード、
さらにその子が「body」ノード
さらに「h1」「p」などが階層的につながる
という木になり、これがWebページの構造の“本体”となります。
この一連のパースとDOM構築により、HTML文書はブラウザで表示され、同時にJavaScriptなどによる動的な操作の対象にもなります。