この記事の目次
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の使い方の実践ステップ
- JavaScript を
js/main.jsのような別ファイルに書きます。 - HTML に
<script src="js/main.js" defer></script>を書きます。<head>の中でも、</body>の直前でもかまいません。 - ブラウザで開き、開発者ツールの Console に赤いエラーがないことを確かめます。
- 複数のスクリプトを読み込むときは、使われる側(ライブラリなど)を先に書きます。
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の使い方の関連項目
- querySelectorとは|使い方・querySelectorAllとの違い・nullエラー対策(近日公開)
- addEventListenerとは|使い方・once・解除・thisの注意点(近日公開)
- let・const・varの違い|使い分けとスコープの基本
- ブラウザの開発者ツールの使い方|要素・Console・スマホ表示
- $(document).ready()とDOMContentLoadedの違い|書き方と3.0の変更(近日公開)

