web-dev-qa-db-ja.com

HTMLマークアップの<script>タグはどこに置くべきですか?

HTMLドキュメントにJavaScriptを埋め込むとき、<script>タグとJavaScriptを含めるための適切な場所はどこですか。 <head>セクションにこれらを配置することは想定されていませんが、<body>セクションの先頭に配置するのは不適切です。ページが完全にレンダリングされる前にJavaScriptを解析する必要があるためです。 )これは、<body>タグの論理的な場所として、<script>セクションの end を残すようです。

それでは、<script>タグを配置するのに適切な場所です。

(この質問は この質問 を参照しています。JavaScriptの関数呼び出しは<a>タグから<script>タグに移動する必要があります。私は特にjQueryを使用していますが、より一般的な回答も適切です。

1312
mipadi

ブラウザが<script>タグを含むWebサイトを読み込むと、次のようになります。

  1. HTMLページを取得します(例:index.html)
  2. HTMLの解析を始めます
  3. パーサーは、外部スクリプトファイルを参照する<script>タグを見つけました。
  4. ブラウザがスクリプトファイルを要求します。その間、パーサーはあなたのページ上の他のHTMLの解析をブロックし停止します。
  5. しばらくするとスクリプトがダウンロードされ、続いて実行されます。
  6. パーサーは、残りのHTML文書の構文解析を続けます。

ステップ#4ではユーザーエクスペリエンスが悪くなります。すべてのスクリプトをダウンロードするまで、Webサイトは基本的に読み込みを停止します。ユーザーが嫌いなことが1つあるとしたら、Webサイトが読み込まれるのを待っていることになります。

なぜこれが起こるのですか?

どのスクリプトでも、document.write()や他のDOM操作を介して独自のHTMLを挿入できます。これは、パーサは、スクリプトがダウンロードされ実行されるまで待ってからドキュメントの残りの部分を安全に解析できるようにする必要があることを意味します。結局のところ、スクリプトは 可能性があります 独自のHTMLをドキュメントに挿入しました。

しかし、ほとんどのJavaScript開発者はもはやDOMを操作しません while ドキュメントがロードされています。代わりに、ドキュメントが変更される前にドキュメントがロードされるまで待機します。例えば:

<!-- index.html -->
<html>
    <head>
        <title>My Page</title>
        <script type="text/javascript" src="my-script.js"></script>
    </head>
    <body>
        <div id="user-greeting">Welcome back, user</div>
    </body>
</html>

Javascript:

// my-script.js
document.addEventListener("DOMContentLoaded", function() { 
    // this function runs when the DOM is ready, i.e. when the document has been parsed
    document.getElementById("user-greeting").textContent = "Welcome back, Bart";
});

ブラウザはmy-script.jsがダウンロードされて実行されるまでドキュメントを変更しないことを認識していないため、パーサーは解析を停止します。

時代遅れのおすすめ

この問題を解決するための古い方法は、パーサーが最後までブロックされないようにするため、<script>タグを<body>の末尾に配置することでした。

このアプローチにはそれ自身の問題があります。ブラウザはドキュメント全体が解析されるまでスクリプトのダウンロードを開始できないということです。大きなスクリプトとスタイルシートを含む大規模なWebサイトでは、できるだけ早くスクリプトをダウンロードできることがパフォーマンスにとって非常に重要です。あなたのウェブサイトが2秒以内にロードされない場合、人々は他のウェブサイトに行くでしょう。

最適な解決策では、ブラウザはできるだけ早くあなたのスクリプトをダウンロードし始め、同時にあなたのドキュメントの残りの部分を解析します。

現代のアプローチ

今日、ブラウザはスクリプトのasync属性とdefer属性をサポートしています。これらの属性は、スクリプトがダウンロードされている間も解析を続けても安全であることをブラウザに伝えます。

非同期

<script type="text/javascript" src="path/to/script1.js" async></script>
<script type="text/javascript" src="path/to/script2.js" async></script>

Async属性を持つスクリプトは非同期的に実行されます。これは、その間ブラウザをブロックすることなく、スクリプトがダウンロードされると同時に実行されることを意味します。
これは、スクリプト1の前にスクリプト2をダウンロードして実行することが可能であることを意味します。

http://caniuse.com/#feat=script-async によると、すべてのブラウザの94.57%がこれをサポートしています。

延期する

<script type="text/javascript" src="path/to/script1.js" defer></script>
<script type="text/javascript" src="path/to/script2.js" defer></script>

延期属性を有するスクリプトが順番に実行される(すなわち、最初のスクリプト1、次にスクリプト2)。これもブラウザをブロックしません。

非同期スクリプトとは異なり、遅延スクリプトはドキュメント全体が読み込まれた後にのみ実行されます。

http://caniuse.com/#feat=script-defer によると、すべてのブラウザの94.59%がこれをサポートしています。 94.92%が少なくとも部分的にそれを支持している。

ブラウザの互換性に関する重要な注意:状況によってはIE <= 9が遅延スクリプトを順不同で実行する可能性があります。これらのブラウザをサポートする必要がある場合は、 this を最初に読んでください。

結論

現在の最先端技術は、スクリプトを<head>タグに入れて、asyncまたはdefer属性を使用することです。これにより、ブラウザをブロックせずにスクリプトをできるだけ早くダウンロードできます。

良いことは、あなたのウェブサイトはまだ他の94%をスピードアップしている間これらの属性をサポートしないブラウザの6%で正しくロードするべきであるということです。

1659
Bart

に記載されているように、bodyタグを閉じる直前

http://developer.yahoo.com/performance/rules.html#js_bottom

スクリプトを一番下に置く

スクリプトによって引き起こされる問題は、それらが並列ダウンロードをブロックすることです。 HTTP/1.1仕様では、ブラウザはホスト名ごとに2つ以下のコンポーネントを同時にダウンロードすることを推奨しています。複数のホスト名から画像を提供している場合は、3つ以上のダウンロードを並行して実行できます。スクリプトがダウンロードされている間、ブラウザは異なるホスト名であっても他のダウンロードを開始しません。

225
Cammel

ノンブロッキングスクリプトタグは、ほぼどこにでも配置できます。

<script src="script.js" async></script>
<script src="script.js" defer></script>
<script src="script.js" async defer></script>
  • async scriptは、使用可能になると同時に非同期に実行されます。
  • defer スクリプトはドキュメントの解析が終了したときに実行されます
  • async deferasyncがサポートされていない場合、scriptは遅延動作にフォールバックします。

そのようなスクリプトは非同期に/ドキュメントの準備ができた後に実行されます。つまり、これはできません。

<script src="jquery.js" async></script>
<script>jQuery(something);</script>
<!--
  * might throw "jQuery is not defined" error
  * defer will not work either
-->

またはこれ:

<script src="document.write(something).js" async></script>
<!--
  * might issue "cannot write into document from an asynchronous script" warning
  * defer will not work either
-->

またはこれ:

<script src="jquery.js" async></script>
<script src="jQuery(something).js" async></script>
<!--
  * might throw "jQuery is not defined" error (no guarantee which script runs first)
  * defer will work in sane browsers
-->

またはこれ:

<script src="document.getElementById(header).js" async></script>
<div id="header"></div>
<!--
  * might not locate #header (script could fire before parser looks at the next line)
  * defer will work in sane browsers
-->

とは言っても、非同期スクリプトには次のような利点があります。

  • リソースの並列ダウンロード
    ブラウザは、スクリプトがダウンロードされて実行されるのを待たずに、スタイルシート、画像、その他のスクリプトを同時にダウンロードできます。
  • ソース順序の独立性
    ブロックを気にせずにスクリプトを頭や体の中に入れることができます(CMSを使用している場合に便利です)。実行順序はまだ重要です。

コールバックをサポートする外部スクリプトを使用することによって、実行順序の問題を回避することが可能です。多くのサードパーティのJavaScript APIは現在、ノンブロッキング実行をサポートしています。これは Google Maps APIを非同期でロードする例です

65
Salman A

Yahoo!が推奨する標準的なアドバイス。 Exceptional Performanceチームは、<script>タグをドキュメント本体の最後に配置して、ページのレンダリングをブロックしないようにします。

しかし、Google AnalyticsのJavaScriptファイルのロード時間についての この回答 で説明されているように、より良いパフォーマンスを提供する新しいアプローチがいくつかあります。

すばらしいスライド Steve Souders(クライアントサイドのパフォーマンスエキスパート)によると、

  • 外部JavaScriptファイルを並行してロードするためのさまざまな手法
  • 読み込み時間とページレンダリングへの影響
  • ブラウザに表示される「進行中」のインジケータの種類(ステータスバーの「読み込み中」、砂時計のマウスカーソルなど)。
36
orip

JQueryを使用している場合は、JavaScriptを最適な場所に配置し、$(document).ready()を使用して、関数を実行する前に正しくロードされるようにします。

ちなみに、<head>セクションにある私のスクリプトタグはすべて最もきれいな場所のようです。

22
Andrew Hare

XHTMLスクリプトがhead要素内以外の場所にあるかどうかを検証しません。 それはどこにでもあることがわかります。

JQueryのようなもので実行を延期することができるので、それがどこに配置されていても関係ありません(解析中のわずかなパフォーマンスのヒットを除く)。

9
Allain Lalonde
<script src="myjs.js"></script>
</body>

scriptタグは、常にbody closeまたはHTMLの下部 fileの前に使用してください。

その後、js fileをロードする前に、ページのコンテンツを最初に見ることができます。

必要ならこれをチェックしてください: http://stevesouders.com/hpws/rule-js-bottom.php

8
AmanKumar

これまでの(そして広く受け入れられている)答えは「一番下」です。その場合、何かが実行を開始する前にDOM全体がロードされていたはずです。

さまざまな理由で、page onloadイベントで意図的に実行を開始するために利用可能なプラクティスから始めて、反対者がいます。

5
dkretz

2019年の最新のアプローチはES6モジュールタイプのスクリプトを使用することです

<script type="module" src="..."></script>

デフォルトでは、モジュールは非同期にロードされ防御されます。つまり、どこにでも配置でき、それらは並行してロードされ、ページのロードが完了したときに実行されます。

スクリプトとモジュールの違いは以下のとおりです。

https://stackoverflow.com/a/53821485/731548

スクリプトと比較したモジュールの実行について説明します。

https://developers.google.com/web/fundamentals/primers/modules#defer

サポートはここに示されています:

https://caniuse.com/#feat=es6-module

2
cquezel

スクリプトとその使用法に応じて、(ページのロードとレンダリング時間に関して)最善の方法は、従来の<script>タグ自体を使用せずに、スクリプトのロードを非同期に動的にトリガーすることです。

いくつかの手法がありますが、最も簡単な方法は、window.onloadイベントが発生したときにdocument.createElement( "script")を使用することです。その後、ページ自体がレンダリングされたときにスクリプトが最初にロードされるので、ユーザーがページが表示されるのを待たなければならない時間に影響を与えません。

これは当然スクリプト自体がページのレンダリングに必要ではないことを必要とします。

詳しくは、Steve Souders(YSlowの作成者であるが現在はGoogleにある)による投稿 Coupling async scripts を参照してください。

1
stpe

最後にスクリプトを含めるのは、Webサイトのコンテンツ/スタイルを最初に表示する場合に主に使用されます。

頭にスクリプトを含めると、スクリプトが早くロードされ、Webサイト全体をロードする前に使用できます。

スクリプトが最後に入力された場合、検証はスタイルとデザイン全体をロードした後にのみ行われます。これは、応答の速いWebサイトには不適切です。

0
Sanjeev S

ページのスタイルを設定したり、ページ内のアクションを使用したりするために必要なスクリプト(ボタンをクリックするなど)を読み込んでいる場合は、それを一番上に配置することをお勧めします。あなたのスタイルが100%CSSで、あなたがボタンアクションのためのすべての代替オプションを持っているなら、あなたはそれを一番下に置くことができます。

あるいは、それが気にならない場合は、モーダルロードボックスを作成し、JavaScriptをページの一番下に配置し、スクリプトの最後の行がロードされたときにそれを消すことができます。これにより、スクリプトがロードされる前に、ユーザーがページ内でアクションを使用するのを防ぐことができます。また不適切なスタイリングも避けてください。

0
ahmedmzl
  • それでもIE <10でのサポートとパフォーマンスに関心がある場合は、必ずスクリプトタグをHTML本体の最後のタグにすることをお勧めします。そうすれば、DOMの残りの部分がロードされたことが確実にわかります。ブロックしたりレンダリングしたりすることはありません。

  • IE <10についてあまり気にしないのであれば、スクリプトをドキュメントの先頭に置き、deferを使用してDOMがロードされた後にのみ実行されるようにします(<script type="text/javascript" src="path/to/script1.js" defer></script>)。それでもコードをIE <10で動作させたい場合は、コードをwindow.onloadで囲むことを忘れないでください。

0
user5803163

Webページの実行に依存すると思います。最初にJavaScriptをロードしないと表示したいページが正しく表示されない場合は、最初にJavaScriptファイルを含める必要があります。しかし、最初にJavaScriptファイルをダウンロードしなくてもWebページを表示またはレンダリングできる場合は、JavaScriptコードをページの下部に配置する必要があります。それは迅速なページロードをエミュレートするので、そしてユーザーの観点からはそれはそのページがより速くロードされているように思われるでしょう。

0
Amit Mhaske

スクリプトは、DOMがロードされ実行されるまで、DOMロードをブロックします。

スクリプトを<body>の最後に置くと、すべてのDOMがロードおよびレンダリングされる可能性があります(ページの表示が速くなります)。 <script>は、これらすべてのDOM要素にアクセスできます。

一方、<body> start以降の後に配置すると、スクリプトが実行されます(まだDOM要素はありません)。

あなたはjQueryをインクルードしています、つまりあなたが望むところならどこにでもそれを置くことができ、 .ready()

0
Szymon Toda

<script>の参照の大部分は、<body>の末尾に配置できます。
しかし、あなたのページに外部スクリプトを使っているアクティブなコンポーネントがあるなら、
その場合、それらの依存関係(jsファイル)はその前にくるべきです(理想的にはheadタグ内)。

0
Tech AG

HTMLドキュメントの最後に

実行時にブラウザへのHTMLドキュメントのロードに影響しないようにします。

0
Mr_Blue

<script>タグを配置するのに最適な場所は</body>タグを閉じる前です

また、jsファイルを外部にロードすることには、独自の利点がありますブラウザによってキャッシュされるのようにページのロード時間を短縮する、それHTMLコードとJavaScriptコードを分離およびコードベースの管理を改善

しかし、最新のブラウザは、asyncdeferのような外部のjavascriptファイルをロードする他の最適な方法もサポートしています。

非同期と遅延

通常、HTMLページの実行は行ごとに開始されます。外部JavaScript要素が検出されると、JavaScriptがダウンロードされて実行可能になるまで、HTML解析は停止されます。この通常のページ実行は、deferおよびasync属性を使用して変更できます。

Defer

Defer属性を使用すると、JavaScriptはHTML解析と並行してダウンロードされますが、完全なHTML解析が完了した後にのみ実行されます。

<script src="/local-js-path/myScript.js" defer></script>

Async

Async属性を使用すると、スクリプトが検出されるとすぐにJavaScriptがダウンロードされ、ダウンロード後、HTML解析とともに非同期に(並列に)実行されます。

<script src="/local-js-path/myScript.js" async></script>

どの属性を使用するか

  • スクリプトが他のスクリプトから独立しており、モジュール式である場合は、asyncを使用します。
  • asyncでscript1とscript2をロードしている場合、両方が実行されます
    ダウンロードと同時にHTML解析と並行して
    および利用可能。
  • スクリプトが別のスクリプトに依存している場合は、両方にdeferを使用します。
  • Script1とscript2がdeferを使用してこの順序でロードされると、script1が最初に実行されることが保証され、
  • 次に、script1が完全に実行された後、script2が実行されます。
  • Script2がscript1に依存する場合、これを行う必要があります。
  • スクリプトが十分に小さく、タイプasyncの別のスクリプトに依存している場合は、属性なしでスクリプトを使用し、すべてのasyncスクリプトの上に配置します。

参照: knowledgehills.com

0
Haritsinh Gohil