質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

89.99%

scriptタグはなんで通常bodyに書くのか。

受付中

回答 8

投稿

  • 評価
  • クリップ 56
  • VIEW 52K+

MensJink

score 81

どうもこんにちは。
先にお伝えしますと、この質問は技術的興味から来た質問です。
まず、HTMLのコードで以下の書き方をよく見かけます。

<!doctype html>
<html>
<head>
    <link rel="stylesheet" href="http://example.com/">
    <meta charset="utf-8">
    <title></title>
</head>
<body>
<script src="http://example.com/"></script>
</body>
</html> 


このコードでscriptタグをbodyタグの下に書いている理由をご教授していただきたいということが今回の質問内容です。
稚拙な質問で恐縮ですが、よろしくおねがいします。

  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 8

+78

scriptタグの記述場所は別にどこでも構わないのですが、bodyタグの終端に記述する理由は以下のような理由があるのではないかと思います。

  • javascriptファイルを読み込んでいる間は、HTMLファイルを読み込まないため、ページのレンダリングを行わせてからjavascriptファイルを読み込むことで表示速度を早くする。
  • CSSはheadタグ中に、javascriptはbodyタグの下にまとめて記述することでわかりやすくなる。

ただし、HTMLが解析される前に実行されるべきjavascriptファイルなどはheadタグ内に記述するべきだと思います。
headタグ内にscriptタグを置いたときには、javascriptファイルが最初に読み込まれるので、そのjavascriptファイルのサイズが巨大だった場合、ページの表示に時間がかかることになります。その解決策として、async属性という非同期的にjavascriptファイルを読み込むことができるようになる属性を使います。ただし、非同期的にjavascriptファイルを読み込むということは、ファイルが複数ある場合にどれが最初に読み込まれるかわからないということです。なので、もしもA.jsB.jsというファイルがあって、絶対にA.jsから先に読み込む必要があったとしても、async属性を使うとB.jsから読み込まれてしまうことがあります。また、一部ブラウザがこの属性に対応していないので注意する必要があります。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

+16

scriptタグをbodyタグの下に書いている理由

SEOの観点です。

大前提として、scriptタグをHTML内に挿入すると、
そのscriptを定義すると、一度その時点でページのレンダリングはストップします。
srcが定義されているならファイルをダウンロードし、全ての行の実行が完了してからページのレンダリングを再開します。

HTMLとCSSで人間が理解出来るページがほぼ大多数を占めています。
なので、最初に見る画面としてはJavaScriptは存在する必要はありません。

3秒以内にページが表示されないとユーザーの4割は直帰してしまうという統計データがあるそうです。
「SEO 3秒」等で調べてみてください。
要するにユーザーに見せる画面は早ければ速いほどよいという考え方です。


その辺の経緯から、様々なノウハウが蓄積されていきました。

  • JavaScriptは慎ましく
  • 初動のレンダリングにJavaScriptは関係ないんだから下に書け

これはGoogleのサーチエンジンのコンセプトにも取り入れられており、
上記の条件に準拠したページはSEOとして順位にプラスの評価値がつきます。


この仕組みを利用する手段もあります。

例えばサイト改善の手法の1つにA/Bテストがあります。
ランダムに2~3パターンのページをどれを表示するかを決定し、
どのページに割り振られたユーザーがそのサイトに好意的だったかを調べてサイト改善の材料にします。

このA/BテストのOptimizelyでは、
Headタグ内にスクリプトを設置すると、読み込みが終わるまでページのレンダリングを行わないという仕様を逆手に取り、
あえてHeadタグ内にOptimizelyのタグを埋め込み、対象ページの選定やらページの書き換え内容を宣言した後に、ページをレンダリングさせます。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

+11

順番に読み込む関係上、DOMが出来上がっていない状態でのスクリプト実行だとタイミングが合わないことがあるからです。
外部に記述する場合は、DOMの読み込みが終わった事をトリガーに実行すれば問題ありません。
bodyの閉じタグの手前で読み込んでも良いです。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

+10

(通常ではありませんが)エレメントのロードが終わってからスクリプトが実行されるからです。
例えば

var btn = document.getElementById('btn');


というコードを書いた<script>を<head>内に書いた場合は、btnが取得できません。(window.onloadやwindow.addEventListener('DOMContentLoaded')などイベント後は取得できる)
ただ、<head>に書いても<script defer src="hoge.js">としてdeferロードを設定した場合もエレメントのロードが終わってから実行されます。

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

+7

すでに書かれていますが、script タグ自体、header タグの中、body タグの中のどこに書いても構いません。

Javascript が読み込まれている間「HTMLが読み込まれない」のではなく「レンダリングがブロックされる = script タグ以降が表示されない」というのが正しいですね。

なので、表示された後に実行されてよい script は、邪魔にならない場所に書くのが表示速度の面からはベターということになります。ページの要素の最後に書く、ということですね。

defer 属性や async 属性を与えることで、レンダリングのブロックを防ぐことは可能ですが、ブラウザによる差異があったり、読み込まれる順番が重要だったりする場合があるので使用されなかったりします。

async で非同期読込にした場合、Jquery 本体より、プラグインのほうが先に解釈されたりするとまずかったりする場合がありますね。
defer だと、ページの読み込みが完了してから script が解釈されますが、ブラウザによっては対応してなかったりします。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

+6

WebブラウザはHTMLファイルの上の行から順にレンダリングしていくので、処理に時間のかかるスクリプトが上の方にあると、「なかなか内容が表示されない」なんてことになるから、じゃないでしょうか。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

+5

仕様の話をきちんとするか、推奨される実装の話をするか、多くの実装の話をするのかで、答えが異なってきます。正確に言うと、「どこまできちんと言うか」が異なってきます。私も仕様書を読み込んでいるわけではないので、間違っているところがあるかもしれません。
きちんと書くように…と言いながら、私も、一部端折りながら書いていますし、JavaScript はほとんど扱わないので、間違っているところもあるかもしれません。

sysyz さんの回答が、技術的に正しく、まとまっていると思います。

動作理解の把握のための比較的質の良い文献が、JavaScriptの記入場所…タグ内の記述の言及があるので参考に、JavaScriptの記述場所まとめパターンの列挙、JavaScriptの読み込みにおける非同期スクリプト注入の悪影響旧石器時代のJavaScriptを書いてる各位に告ぐ、現代的なJavaScript超入門 Section1 ~すぐにでも現代っぽく出来るワンポイントまとめ~ あたりでしょうか。

async defer に関連しては、async/defer 属性と DOM 構築 で体感できます。scriptのdefer/asyncを理解し、ページの高速化方法を探るサイトに適したリソース配置とasync/defer完全マスター – レンダリング優先のグッド・プラクティスdocument.writeを使った遅いブログパーツ(例えばzenback)を非同期化してサイトを高速表示する方法 が良くまとまっています。ぜひ読んでください。

 本来は記述位置に依存する

まず

  • script タグ は、そのタグがある位置によって(HTML ソースに与える)実行結果が異なる

ことは知っておかなければなりません。

document_write.js
として

document.write("document write!");


があった場合、

<!doctype html>
<html>
<head>
    <meta charset="utf-8">
    <title></title>
</head>
<body>
<script src="document_write.js"></script>
ABC
<script src="document_write.js"></script>
</body>
</html>

document write! ABC document write!

という出力になります。2つの "document write!" は script タグの位置に依存しています。つまり、どこに書いても良いと端的に述べてしまうのは大きな誤りなのです。

ただ、現在は document.write は非推奨になっています。「問題がある」のです。

 記述位置に依存しないスクリプトが求められる

記述位置に依存するということが分かると(いなくても生じる問題もありますが)、次の問題が生じます。

  • script タグの JavaScript が実行されたあとでないと、「正しい」ドキュメントが得られない

例えば、document.write("<div class='script'>"); とあるのと、HTML 文書に <div class='script'> があるのとは同じレンダリング結果にならないとおかしいですね。スクリプト実行後は再度、HTML ソース全体の解析をしなければならなくなります。
これが、JavaScriptの記述場所まとめのいう、「HTMLのレンダリング前に実行する必要があ」るということです。

このような処理が多いと問題が大きいので、innerHTML や insertAdjacentHTML 他、「ブラウザが把握している HTML の構造(DOM) に手を入れるスクリプト」を「DOM が準備できた後に」実行することが増えてきました。「旧石器時代の~」に載っているようなことです。
document.getElementById("text"); を使ってあげれば「場所の指定」を「HTML ソース上の id」で指定できるので、特定の場所に特定の記述をさせることが可能になります。

 その他

 body タグの最後や head タグ内の最後に書く利点・理由

あとは、他の方の記述の方が分かりやすいし、詳しいでしょう。

「記述位置に依存しない」のであれば、「いつ・どのように」実行されても良いでしょう。ここで、ブラウザの HTML ソースの解釈を邪魔せず、できるだけ早くページの概況を表示させるため

  • body タグの最後

に書く選択肢が生まれてきます。一方で、head 内にある利点もあるのです。

  • (私は詳しくないが) HTMLが解析される前に実行されるべきjavascriptファイル がある…そうです
  • HTML ソース内の早い段階に現れるため、ブラウザは早く取得できる…body 末尾にあると、ソースを全部読み終えないと、script タグの外部ソースがあることに気づかないという問題があります。必要なスクリプトの実行開始がどんどん遅れてしまいます。
  • ライブラリなど、ソースファイル間には依存関係があることがある…jquery なんかはその例なのでしょうか?これは、「先に」書く必要があるため、head 内に入れておきます。

といった具合です。もう少しコントロールしたいですよね。

 defer, async によるロード

defer ありでは

  • HTML と並行して、非同期でロード
  • レンダリング後に同期的に実行

されます。head タグ内に書く「ブラウザは早く取得できる」メリットは活かしながら、body タグ最後にあるような、「あとで実行」を実現できるわけです。

また、「『DOM が準備された後に実行するコード』を登録するコードを実行」するのは、DOM が準備される前でも良いはずです。async ありでは

  • レンダリングと並行して非同期で、ロード完了次第実行

実行されます。

ということで、document.write は弊害が大きいため、避けられるようになり、結果として、「どこに script タグがあっても動作する」プログラムが求められてきました。文法上は、script タグは body 内でなければならない、ということはありません。

一方で、ソースコード間の依存性がある場合、「読み込むソースの順序」は動作に影響を与えます。記述が「どこでも構わない」ということはありませんから、挙動を把握して記述するようにされてください。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

+4

すんごいざっぱな私の認識

大前提
インタプリタ言語なので、上から順番に読み込まれる。

前提
header部分で共通用のjsファイルが読み込まれた後以降なら、どこに書いてもいい。
※読み込み順の依存関係が関係してくる問題です。

実装
SEOタグなら、上部近辺にまとめて書いておくと探しやすくていい。
新規に追加するスクリプトなら一番下に書いて、「自分の実装で影響する範囲を特定しやすく」しておく。
※一番最後にすることで、前のスクリプトに迷惑かけないようにする狙いもあり。

jsエラー出ると、以降の処理が全部とまるので、意外と一番最後に書くの大事です・・・。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 89.99%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

同じタグがついた質問を見る