<script>
| 対応: | HTML 4(1997) |
|---|
『script』はJavaScriptのコードを記述したり、外部JSファイルを読み込んだりするための要素です。
構文
<!-- インラインでJavaScriptを記述 -->
<script>
console.log("Hello!");
</script>
<!-- 外部ファイルを読み込む -->
<script src="app.js"></script>
<!-- 非同期読み込み(defer推奨) -->
<script src="app.js" defer></script>
主な属性
| 属性 | 概要 |
|---|---|
| src | 外部JavaScriptファイルのURLを指定します。指定した場合、タグ内のインラインコードは無視されます。 |
| type | スクリプトのMIMEタイプを指定します。省略すると「text/javascript」とみなされます。モジュールを使う場合は「module」を指定します。 |
| defer | HTMLの解析が完了してから、DOMContentLoadedイベントの前にスクリプトを実行します。外部ファイルにのみ有効です。 |
| async | HTMLの解析と並行してスクリプトをダウンロードし、ダウンロード完了後すぐに実行します。実行順序は保証されません。 |
| module | type="module" と指定することでESモジュール形式のスクリプトとして扱われます。デフォルトで『defer』と同様の動作をします。 |
サンプルコード
ESモジュールはJavaScriptファイルを分割して管理する仕組みです。『type="module"』を指定すると、import/export構文が使えるようになります。
sample_script.html
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<title>scriptサンプル</title>
<!-- defer: DOMが構築されてから実行される(head内推奨) -->
<script src="main.js" defer></script>
<!-- async: ダウンロード完了後すぐ実行(順序不問のスクリプトに使用) -->
<script src="analytics.js" async></script>
<!-- ESモジュール形式 -->
<script type="module" src="app.mjs"></script>
</head>
<body>
<p id="message">読み込み中...</p>
<!-- インラインスクリプト(bodyの末尾が伝統的な配置) -->
<script>
// DOMが存在するのでここでは直接操作できる
document.getElementById("message").textContent = "読み込み完了!";
</script>
</body>
</html>
実行結果
ページが読み込まれると、インラインスクリプトによって段落のテキストが書き換えられます。
概要
『script』要素の配置場所と読み込み方法は、ページの表示速度に大きく影響します。『head』内に書いた通常の『script』タグはHTMLの解析をブロックするため、外部スクリプトを読み込む場合は原則として『defer』属性を付けることを推奨します。『defer』を付けると、HTMLの解析を妨げずにバックグラウンドでダウンロードし、DOM構築完了後に実行されます。
『async』は分析ツールや広告タグなど、他のスクリプトに依存せず単独で動作するスクリプトに向いています。複数の『async』スクリプトは実行順序が保証されないため、依存関係のあるスクリプトには使用しないよう注意してください。
ESモジュール(type="module")を使うと、『import』/『export』構文でスクリプトをファイルに分割して管理できます。モジュールはデフォルトで『defer』と同じ動作をし、同一スクリプトは一度しか読み込まれないという特徴があります。スクリプトの実行を完全に無効化したいページでは『noscript』要素を使って代替コンテンツを表示できます。
通常・defer・async の動作比較
3つの読み込み方式でHTML解析とスクリプト実行のタイミングがどう変わるかを整理します。
| 方式 | ダウンロード | HTML解析 | 実行タイミング | 順序保証 |
|---|---|---|---|---|
| 通常(属性なし) | 同期 | ブロックされる | ダウンロード完了後すぐ | ○ |
| defer | 並行 | ブロックされない | DOM構築完了後(DOMContentLoaded前) | ○ |
| async | 並行 | ブロックされない | ダウンロード完了後すぐ(DOMより先の場合あり) | × |
| type="module" | 並行 | ブロックされない | deferと同じ(デフォルト) | ○ |
<!-- 推奨:head内にdeferで記述(DOMが使えるタイミングで実行される) --> <head> <script src="main.js" defer></script> </head> <!-- 独立して動く計測・広告スクリプトはasync --> <script src="https://analytics.example.com/track.js" async></script> <!-- bodyの末尾に書く方法(古典的・確実な方法。deferと同等の効果) --> <body> <!-- コンテンツ --> <script src="main.js"></script> </body>
インラインスクリプトのベストプラクティス
外部ファイルを使わずにHTMLにJavaScriptを直接埋め込む場合のパターンです。
<!-- DOMContentLoadedを待ってからDOMを操作する(head内でも安全) -->
<script>
document.addEventListener("DOMContentLoaded", function() {
var btn = document.getElementById("toggle-btn");
btn.addEventListener("click", function() {
document.getElementById("menu").classList.toggle("open");
});
});
</script>
<!-- JSONデータをHTMLに埋め込んでJSから参照する -->
<script type="application/json" id="app-config">
{"apiUrl": "/api", "version": "1.0", "debug": false}
</script>
<script>
var config = JSON.parse(document.getElementById("app-config").textContent);
console.log(config.apiUrl); // "/api"
</script>
対応ブラウザ
1 以降 ○
1 以降 ○
3 以降 ○
2 以前 ×
8 ○
7 ○
6 ○
12.1 以降 ○
11.1 以前 ×
2 以降 ○
Android Browser
4.4 以降 ○
4 以前 ×※ バージョン情報は MDN に基づいています。
記事の間違いや著作権の侵害等ございましたらお手数ですがこちらまでご連絡頂ければ幸いです。