HTML に JavaScript を読み込む
このレッスンで分かること
<script src="script.js" defer></script>の 1 行で HTML と JavaScript がつながりますdeferを付けると HTML を全部読み終えてから JavaScript が動きます- 最小例は
function buildScriptTag(src) { return '<script src="' + src + '" defer></script>'; }
HTML に JavaScript を読み込む とは
HTML ファイルに script タグを 1 行足して、外部の JavaScript ファイルを読み込む手順を身につけます。置く場所と defer の意味まで押さえます。
HTML と JavaScript をつなぐ
これまで作ってきた プロフィールサイト は HTML と CSS でできています。HTML が骨組み、CSS が見た目でした。ここに 3 つ目の言語として JavaScript を足すと、サイトが動き出します。ボタンを押したら色が変わる、入力した文字をその場で確かめる、といった「反応する」部分は全部 JavaScript の担当です。
ただし、JavaScript のファイルを作っただけでは何も起きません。ブラウザは HTML を読みに来るので、HTML の側から「このファイルも読んでね」と教えてあげる必要があります。その役目を持つのが script タグです。
<script src="script.js" defer></script>たったこれだけです。この 1 行を HTML に足すと、同じフォルダにある script.js がブラウザに読み込まれ、中に書いた JavaScript が実行されます。
書き方は 2 通りある
JavaScript を HTML に持ち込む方法は 2 つあります。違いを表にまとめます。
| 書き方 | 見た目 | 向いている場面 |
|---|---|---|
| インライン | <script> と </script> の間に直接コードを書く | 動作を数行だけ試したいとき |
| 外部ファイル | <script src="script.js"></script> で別ファイルを読む | 実際のサイト。コードが増えても散らからない |
インラインはこう書きます。
<script>
console.log("プロフィールサイトを読み込みました");
</script>短いうちは楽ですが、コードが 50 行 100 行と増えると HTML が読めなくなります。CSS を style.css に分けたのと同じ理由で、JavaScript も script.js に分けるのが基本です。このコースでも外部ファイル方式で進めます。
HTML / CSS / JavaScript を 3 つのファイルに分けておくと、あとから「見た目だけ直したい」「動きだけ直したい」というときに探す場所が 1 つに決まります。ファイルを分けるのは、未来の自分への親切です。
フォルダの形
プロフィールサイト のフォルダは、次のような形になります。
profile-site/
index.html
style.css
script.jsindex.html の中で style.css と script.js の両方を読み込みます。全体はこうなります。
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8" />
<title>山田 太郎 のプロフィール</title>
<link rel="stylesheet" href="style.css" />
<script src="script.js" defer></script>
</head>
<body>
<h1>山田 太郎</h1>
<p>Web エンジニアを目指しています</p>
</body>
</html>script タグはどこに置くか
script タグは head の中にも body の終わり際にも置けます。どちらでも動きますが、動くタイミングが変わります。ここが初学者のつまずきポイントなので、順を追って見ていきます。
ブラウザは HTML を上から順に読みます。読んでいる途中で script タグにぶつかると、そこでいったん HTML を読むのをやめて JavaScript を実行します。つまり、head に素の script タグを置くと、body の中身がまだ 1 つも存在しない状態で JavaScript が走ります。第 8 章で扱う「HTML の要素を取ってくる処理」は、この状態だと必ず失敗します。
図のとおり、defer を付けるかどうかで実行の順番が変わります。3 つの書き方を比べます。
| 書き方 | 読み込み | 実行のタイミング |
|---|---|---|
<script src="..."> | HTML の読み込みを止めて取得 | 取得した直後にその場で実行 |
<script src="..." defer> | HTML を読みながら並行して取得 | HTML を全部読み終えてから実行 |
<script src="..." async> | HTML を読みながら並行して取得 | 取得できた瞬間に実行。順番は保証されない |
迷ったら defer
結論から言うと、head の中に defer 付きで書くのが今の定番です。理由は次の 2 点です。
- HTML の読み込みを止めないので、表示が速い
- HTML を全部読み終えてから動くので、要素が見つからない事故が起きない
async は解析ツールのタグなど「他のコードと順番が関係ない」ものだけに使います。複数のファイルを async で読むと、書いた順に実行される保証がありません。入門のうちは defer だけ覚えておけば十分です。
bodyの閉じタグ直前にscriptタグを置く書き方も昔からよく使われます。これも「HTML を読み終わってから実行される」ので安全です。ただし取得の開始が遅れる分、deferのほうがわずかに速くなります。
課題ではタグを文字列で組み立てる
このコースの課題は、関数を書いて戻り値をテストする形式です。そこで今回は、覚えた script タグの形を 文字列として組み立てて返す関数 を書いてもらいます。手で書いたタグを、そのままプログラムに言わせてみる、という練習です。
function buildLinkTag(href) {
return '<link rel="stylesheet" href="' + href + '" />';
}
console.log(buildLinkTag("style.css"));
// => <link rel="stylesheet" href="style.css" />' と " を使い分けているところに注目してください。組み立てたい文字列の中に " が入っているので、文字列全体はシングルクォート ' で囲んでいます。逆にすると、途中で文字列が切れてしまいます。
| 囲む記号 | 中で使える記号 | 例 |
|---|---|---|
' シングルクォート | " はそのまま書ける | '<a href="#">' |
" ダブルクォート | ' はそのまま書ける | "it's fine" |
同じ記号を中で使いたいときは
\"のようにバックスラッシュで打ち消す方法もあります。ただし読みにくくなるので、まずは囲む記号のほうを変えるのが定石です。
よくある間違い
- パスを間違えている —
script.jsをjsフォルダに入れたのにsrc="script.js"のままだと読み込めません。開発者ツールの Network タブに 404 と出ます。src="js/script.js"のようにフォルダ名から書きます
<!-- 誤り。js フォルダの中にあるのに書いていない -->
<script src="script.js" defer></script>
<!-- 正しい -->
<script src="js/script.js" defer></script>- 閉じタグを省略する —
<script src="script.js" defer />のような自己閉じは効きません。scriptタグは必ず</script>で閉じます
<!-- 誤り。自己閉じは効かない -->
<script src="script.js" defer />
<!-- 正しい -->
<script src="script.js" defer></script>- defer を付けずに head に置く — HTML がまだ組み上がっていない状態で走るため、第 8 章以降で
nullが返る原因になります。headに置くときはdeferとセットにします
<!-- 誤り。body がまだ空の状態で実行される -->
<script src="script.js"></script>
<!-- 正しい -->
<script src="script.js" defer></script>要件
- 関数名は
buildScriptTag、引数はsrcの 1 つ (文字列) - 戻り値は
<script src="(src の値)" defer></script>という文字列 - 属性値を囲むダブルクォートも文字列に含めること
srcが空文字のときも、そのまま空の属性値として組み立てること
入出力例
buildScriptTag("script.js") → "<script src="script.js" defer></script>"
buildScriptTag("js/main.js") → "<script src="js/main.js" defer></script>"
buildScriptTag("assets/js/profile.js") → "<script src="assets/js/profile.js" defer></script>"
buildScriptTag("") → "<script src="" defer></script>"