HTML

The HTML script tag is used to incorporate JavaScript code, which adds dynamic features and behaviors to a web page.

script要素

<script> とは?

HTMLの <script> タグは、Webページに動的な振る舞いを追加するために使用されます。これにより、ページ上でユーザーとのインタラクションが可能になり、静的な文書をはるかに興味深く有用なものに変えることができます。一般的に、JavaScript(JS)というプログラミング言語がこの目的のために使われます。

基本は <head> に書いて defer または type="module" を付けます(表示を止めず、実行順も安定します)。async は順序不要の計測タグなどに向きます。

<script>タグの基本

<script> タグを使用する基本的な方法は、直接 JavaScriptコードを HTML内に書き込むか、外部の JavaScriptファイルを参照するかの二つがあります。直接書き込む場合は、<script> タグの内部に JavaScriptコードを記述します。外部ファイルを参照する場合は、src 属性を使用してファイルの場所を指定します。

src 属性で JavaScriptの外部 jsファイルを読み込む場合には、例えば以下のように記述します。

HTML

<script src="sample.js"></script>

インラインで JavaScript を書くときは、そのまま <script> の中に記述します。HTMLコメントで囲む必要はありません。

HTML

<script>
	console.log("Hello, script!");
</script>

セキュリティ面の考慮

Web開発では、セキュリティは極めて重要です。スクリプトの使用にあたっては、クロスサイトスクリプティング(XSS)のような攻撃から保護するため、信頼できるコードのみを使用し、ユーザー入力を適切にサニタイズすることが重要です。また、可能な限り HTTPS経由で外部スクリプトを読み込むことを推奨します。

属性

src属性
外部スクリプトファイルの URLを指定する。
type属性
スクリプトの言語タイプやデータ形式を指定するために使用されます。
charset属性
外部スクリプトファイルの文字エンコーディングを指定する。
async属性
利用可能な時点でスクリプトを実行する。
defer属性
HTML文書を読み込んだ時点でスクリプトを実行する。

src属性

src 属性は、外部のスクリプト・ファイルのアドレスを指定します。src 属性を指定した場合は、script 要素の中に、インラインでコードを記述する事はできません。

type 属性を使ってスクリプトのタイプを指定した場合、src 属性を使って読み込まれるスクリプトのプログラム言語の種類と一致しなければいけません。

type 属性を指定しない場合は、そのスクリプト・ファイルのプログラム言語は JavaScriptでなければいけません。

src属性のマークアップ例

HTML

<script src="example.js"></script>

type属性

type 属性は、主にスクリプトの言語タイプやデータ形式を指定するために使用されます。しかし、HTML5以降では、JavaScriptがデフォルトのスクリプト言語となっているため、type 属性を指定しなくても JavaScriptとして解釈されます。それでも、特定のケースや古いブラウザの互換性、またはスクリプトがデータブロックとして扱われるべき場合に type 属性が利用されることがあります。

以下は、HTMLの <script> 要素で使用される type 属性の値と、それぞれの簡単な説明です。

(type は省略が既定)
JavaScriptを読み込むだけなら type は書かなくてOK。HTML標準の既定でJavaScriptとして扱われます。
module
type="module" はモジュールを読み込みます。HTMLの読み込み後に実行(実質 defer と同じタイミング)、import/export が使え、ファイルごとにスコープが分かれ、トップレベル await も使えます。古いブラウザ向けに nomodule の併用も可能です。
text/javascript, text/ecmascript, application/javascript, application/ecmascript
いずれも歴史的な表現です。通常は type を書かずに読み込みます(サーバは適切なMIMEタイプを返す必要があります)。
text/plain
実行しない “データ置き場” として使えます。ブラウザはスクリプトとしても画面表示としても扱いません。見せたい場合は <pre><code> を使うか、別のJSで取り出して描画します。
カスタムMIMEタイプ(例: application/x-my-custom-type)
特定のスクリプト処理システムやライブラリ用にカスタマイズされた MIMEタイプを使用することもあります。これらは通常、データブロックとしてスクリプトを埋め込む際や、特定の処理をトリガーするために用いられます。

現代の Web開発では、特に指定する必要がない場合は type 属性を省略し、JavaScriptコードとしての解釈を前提とするのが一般的です。また、モジュールスクリプトを利用する際には type="module" を使用することが推奨されます。

なお、旧来から使われてきた language 属性は、HTML5では非準拠となりますので注意してください。

charset属性

今日では推奨されません。外部スクリプトの文字エンコーディングは、ファイル自体をUTF-8で保存し、サーバのHTTPヘッダ(Content-Type)で示すのが基本です。charset は互換目的以外では使わないでOKです。

※ どうしても古い環境で文字化けする場合の最終手段として使われてきましたが、現在はファイルをUTF-8に統一し、サーバ側の設定を整える方が確実です。

async属性

async 属性は、src 属性で指定された外部のスクリプトファイルを非同期で読み込んで、そのスクリプトが実行できるようになったらすぐに実行されるよう指示するための論理属性です。この属性は、src 属性が指定されている場合にのみ利用可能です。

async属性の利用例

HTML

<script src="example.js" async></script>

ふつうの <script src> は、HTMLの読み込み(パース)をいったん止めて、スクリプトをダウンロード→実行します。

一方で async を付けると、ダウンロード中はパースを止めず、ダウンロードが終わった時点でただちに実行します(実行中は一時的にパースが止まることがあります)。そのぶん表示は軽くなりますが、他のスクリプトとの実行順は保証されません

async 属性はHTML5で導入され、現在は主要ブラウザで広く対応しています。

defer属性

defer 属性は、HTMLの読み込み(パース)が終わったタイミングで、スクリプトを書いた順に実行するための論理属性です。この属性は、src 属性が指定されている場合にのみ利用可能です(<script>...</script> 直書きでは不可)。

defer属性の利用例

HTML

<script src="example.js" defer></script>

では、いくつかサンプルを見てみましょう。ここでは、次の JavaScriptの外部ファイルを使います。

example.js

document.getElementById("st").innerHTML = "読み込み完了";

サンプルコード

HTML

<script src="example.js"></script>
<div id="st">ページロード中...</div>

このサンプルは、JavaScriptエラーになります。なぜなら、example.js は、div 要素がブラウザに読み込まれる前に実行されてしまうからです。

次のように、script 要素に defer属性を指定してみましょう。

defer属性を入れたサンプルコード

HTML

<script src="example.js" defer></script>
<div id="st">ページロード中...</div>

この場合は、ページのロードが完了してから example.js が実行されるため、JavaScriptエラーになる事はありません。

この defer 属性は、onload イベント・ハンドラ属性の代わりとして利用する事が可能ですが、JavaScriptが実行されるタイミングは若干異なります。defer 属性が指定された script 要素のスクリプトは、ドキュメントから load イベントが発生する前に実行されます。そのため、onload で指定されたスクリプトより先に実行されることになります。

互換性: 現在は主要ブラウザで広くサポートされています。defer は外部スクリプトで有効になり、HTMLのパースが終わったあとに書いた順で実行され、DOMContentLoaded より前に動きます。なお、type="module" のスクリプトは既定で同様のタイミング(実質 defer 相当)で動きます。

Data on support for the script-defer feature across the major browsers from caniuse.com

<script type="module"> について

スタートガイド(最短で動かす)

まずは2ファイル作成

math.jsmain.js を用意して、HTMLから main.js をモジュールとして読み込みます。

Hello Modules

HTML

<p>Hello Modules</p>
<script type="module" src="./main.js"></script>

math.js

JavaScript

export function add(a, b) {
    return a + b;
}

export const PI = 3.14159;

main.js

JavaScript

import { add, PI } from './math.js';

const result = add(2, 3);
console.log('2 + 3 =', result);
console.log('PI =', PI);

ポイント

nomodule フォールバック(旧ブラウザ配慮)

ほぼ不要な時代ですが、レガシー向けにクラシック版を用意するならこうします。

HTML

<script type="module" src="/modern/main.js"></script>
<script nomodule src="/legacy/bundle.legacy.js"></script>

モジュール対応ブラウザは上だけ実行、非対応は下だけ実行。