HTML に JavaScript を読み込む

生田 陸人
ゆめさくエンジニア / 現役ソフトウェアエンジニア
編集 LuaGate編集部

このレッスンで分かること

  • <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 に分けたのと同じ理由で、JavaScriptscript.js に分けるのが基本です。このコースでも外部ファイル方式で進めます。

HTML / CSS / JavaScript を 3 つのファイルに分けておくと、あとから「見た目だけ直したい」「動きだけ直したい」というときに探す場所が 1 つに決まります。ファイルを分けるのは、未来の自分への親切です。

フォルダの形

プロフィールサイト のフォルダは、次のような形になります。

profile-site/ index.html style.css script.js

index.html の中で style.cssscript.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 の要素を取ってくる処理」は、この状態だと必ず失敗します。

diagram (will load when visible)

図のとおり、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.jsjs フォルダに入れたのに 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>

要件

  1. 関数名は buildScriptTag、引数は src の 1 つ (文字列)
  2. 戻り値は <script src="(src の値)" defer></script> という文字列
  3. 属性値を囲むダブルクォートも文字列に含めること
  4. 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>"

ヒント

main.js
main.js
学習モード

メモ

HTML に JavaScript を読み込む

⌘S で保存