scriptタグとdeferの使い方|読み込み位置とnullエラー

scriptタグとdeferの使い方とは

<script> は、HTML に JavaScript を読み込むためのタグです。JavaScript のコードを直接書くこともできますが、別ファイル(例:js/main.js)にして src 属性で読み込むのが基本です。

初心者がつまずきやすいのは、script を書く場所と、動き出すタイミングです。HTML はブラウザが上から順に読みます。そのため、ボタンがまだ読み込まれていない時点で「ボタンを探す」プログラムが動くと、ボタンが見つからずにエラーになります。この問題を防ぐのが defer 属性です。

基本(書き方と defer の意味)

<script src="js/main.js" defer></script>
  • src … 読み込む JavaScript ファイルの場所(HTML から見たパス)
  • defer … 「HTML を最後まで読み終えてから、このスクリプトを動かす」という指定

MDN によると、defer が付いたスクリプトは、文書の解析が終わってから実行されます。また、ページの準備ができたことを知らせる DOMContentLoaded という出来事は、defer のスクリプトの実行が終わるまで待たされます。defer があれば、<head> の中に書いても、ボタンなどの要素がそろってから動くということです。

書き方 動き出すタイミング 向いている場面
属性なし(<head> 内) その場で読み込んで、すぐ動く 要素を触らないスクリプト
defer HTML を読み終えてから、書いた順に動く 要素を探して操作するスクリプト(基本はこれ)
async 読み込みが終わり次第、すぐ動く(順番は保証されない) 他と関係しない計測用のスクリプトなど
type="module" 既定で defer と同じように後から動く import・export を使うスクリプト

なお、MDN は defer 属性はモジュールスクリプト(type="module")には効果がなく、モジュールは既定で延期されると説明しています。

サンプルコード(実行結果つき)

// js/main.js
const btn = document.querySelector('#hello-btn');
const msg = document.querySelector('#message');

btn.addEventListener('click', () => {
  msg.textContent = 'こんにちは!見に来てくれてありがとう。';
});
<button id="hello-btn" type="button">あいさつする</button>
<p id="message"></p>
<script src="js/main.js" defer></script>

ボタンを押すと、下の段落に「こんにちは!見に来てくれてありがとう。」と表示されました。

動作確認(検証環境と結果)

  • Microsoft Edge(ヘッドレス)、2026年10月。
  • defer 付きで読み込んだ場合:ボタンを押すと文字が表示され、エラーは出ませんでした。
  • <head> の中に defer なしで document.querySelector("#b").addEventListener(...) と書いた場合:Cannot read properties of null (reading 'addEventListener') というエラーが出ました。スクリプトが動いた時点で、まだボタン(#b)が作られていなかったためです。

scriptタグとdeferの使い方の実践ステップ

  1. JavaScript を js/main.js のような別ファイルに書きます。
  2. HTML に <script src="js/main.js" defer></script> を書きます。<head> の中でも、</body> の直前でもかまいません。
  3. ブラウザで開き、開発者ツールの Console に赤いエラーがないことを確かめます。
  4. 複数のスクリプトを読み込むときは、使われる側(ライブラリなど)を先に書きます。defer 同士は書いた順に実行されます。

scriptタグとdeferの使い方の注意点

  • defer と async は、src で外部ファイルを読み込むときに使う属性です。
  • type="module" のスクリプトは、ファイルを直接開く方法(file://)では import を使った読み込みが動きません。ローカルのサーバーで確かめます。
  • </body> の直前に defer なしで書く方法も、要素がそろった後に動くので null エラーは防げます。ただし、<head> に defer 付きで書くほうが、読み込み自体を早く始められます。

scriptタグとdeferの使い方でよくあるミス

  • defer の付け忘れで null エラー: 要素を探すスクリプトには defer を付けます。
  • パスの間違い: スクリプトが読み込めていないと、何も起きません。Network タブで 404 を確かめます。
  • 全角の記号が混じる: ( ) や全角スペースが入るとエラーになります。

scriptタグとdeferの使い方のチェックリスト

  • [ ] JavaScript を別ファイルにし、src で読み込んだ
  • [ ] 要素を操作するスクリプトに defer を付けた
  • [ ] Console にエラーがないことを確かめた
  • [ ] 複数のスクリプトの順番を確認した

scriptタグとdeferの使い方のFAQ(よくある質問)

Q. defer を付けると表示が遅くなりますか?

A. defer のスクリプトは、HTML の読み込みを止めずに並行して取り寄せられるので、表示を遅らせにくい書き方です。

Q. DOMContentLoaded の中に書く方法との違いは?

A. document.addEventListener('DOMContentLoaded', ...) の中に処理を書いても、要素がそろってから動きます。defer を付ければ、この包み込みを書かなくて済みます。

Q. jQuery の $(document).ready() は必要ですか?

A. jQuery を使う既存のコードでは見かけますが、新しく書くなら defer を付けるだけで同じ目的を果たせます。

筆者の見解(scriptタグとdeferの使い方)

私は、初心者には「JavaScript は別ファイルにして、<head> に defer 付きで書く」という1つの型だけを先に覚えることを勧めます。置き場所の選択肢が多いと、動かない原因が増えるからです。async や type="module" は、計測タグを入れるときや、Vue のようなフレームワークに進むときに必要になった時点で覚えれば十分だと考えます。

scriptタグとdeferの使い方の関連項目

出典(一次情報)

タイトルとURLをコピーしました