タイトル: scriptタグの記載場所
SEOタイトル: HTML script タグ配置完全ガイド (defer/async)
| この記事の要点 |
|
結論: 現代のベストプラクティス
例
コンテンツ
script タグの 3 つの読み込みモード
| モード | HTML パース | 実行タイミング | 順序保証 |
|---|---|---|---|
(素) | ブロック | ダウンロード完了次第即実行 | ○ |
| ブロックしない | HTML パース完了後、DOMContentLoaded 前 | ○ |
| ブロックしない | ダウンロード完了次第即実行 | × |
| ブロックしない | defer と同等 | ○ |
歴史: なぜ 末尾に置くテクニックが流行ったか
2000 年代後半〜 2010 年代前半、まだ defer/async が普及していなかった頃、 を に置くと:
- ブラウザは HTML パース中に script タグに遭遇
- JS ファイルのダウンロード・実行が完了するまでHTML パースを停止
- 結果、ユーザーには白画面が長く表示される
これを避けるため、「 の直前に置けば HTML パースは終わってる」というテクニックが広まりました。jQuery 全盛期の Web 制作本はほぼこのスタイルです。
例
コンテンツ
defer 属性 (推奨)
defer を付けると、ブラウザは:
- script を並行ダウンロード (HTML パースをブロックしない)
- HTML パース完了後に、記述順に実行
DOMContentLoadedイベントの直前に実行される
async 属性
async も並行ダウンロードしますが、ダウンロードが完了した順に即実行します。順序は保証されません。
type="module" (ES Modules)
ES Modules (import/export を使うモジュール) は常に defer 扱いです。明示的に defer を書かなくても OK:
Critical CSS との関係 (Web Vitals)
Core Web Vitals の LCP (Largest Contentful Paint) 改善には、ファーストビュー描画を阻害しないことが重要です。defer / async の徹底に加え、Critical CSS のインライン化を組み合わせます:
Resource Hints (preload/prefetch/preconnect)
ヒントを使うとさらに高速化できます:
サードパーティ JS の遅延読込
チャットウィジェット・コメント欄・SNS シェアボタン等、ファーストビューに不要な JS は意図的に遅延させると Web Vitals が上がります:
// ユーザー操作後にチャットウィジェットを読み込む
document.addEventListener('scroll', loadChat, { once: true });
document.addEventListener('click', loadChat, { once: true });
function loadChat() {
const s = document.createElement('script');
s.src = 'https://widget.example.com/chat.js';
s.async = true;
document.head.appendChild(s);
}
// または IntersectionObserver で要素が見えたとき
const obs = new IntersectionObserver((entries) => {
if (entries[0].isIntersecting) {
const s = document.createElement('script');
s.src = '/js/comments.js';
document.head.appendChild(s);
obs.disconnect();
}
});
obs.observe(document.querySelector('#comments-section'));
使い分け早見表
| JS の種類 | 推奨配置 | 属性 |
|---|---|---|
| 自前のアプリケーション JS | head 内 | defer |
| ES Modules | head 内 | type="module" |
| GA / GTM / Facebook Pixel | head 内 | async |
| jQuery + プラグイン | head 内 | defer (順序保持) |
| インライン script (極小) | head 内 or body 内 | 属性不要 |
| レガシーブラウザ対応 (IE11) | body 末尾 | 属性なし |
FAQ
Q: defer と async どちらが速い?
A: ダウンロード速度は同じ。実行タイミングが違うだけです。順序が必要なら defer、不要なら async。
Q: インライン に defer は効く?
A: 効きません。defer/async は外部ファイル (src 指定) にのみ有効です。
Q: body 末尾でも defer は必要?
A: body 末尾なら不要ですが、現代では head + defer に統一すると保守しやすいです。