HTMLドキュメントにJavaScriptを埋め込むとき、<script>
タグとJavaScriptを含めるための適切な場所はどこですか。 <head>
セクションにこれらを配置することは想定されていませんが、<body>
セクションの先頭に配置するのは不適切です。ページが完全にレンダリングされる前にJavaScriptを解析する必要があるためです。 )これは、<body>
タグの論理的な場所として、<script>
セクションの end を残すようです。
それでは、 は <script>
タグを配置するのに適切な場所です。
(この質問は この質問 を参照しています。JavaScriptの関数呼び出しは<a>
タグから<script>
タグに移動する必要があります。私は特にjQueryを使用していますが、より一般的な回答も適切です。
ブラウザが<script>
タグを含むWebサイトを読み込むと、次のようになります。
<script>
タグを見つけました。ステップ#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%で正しくロードするべきであるということです。
に記載されているように、bodyタグを閉じる直前
http://developer.yahoo.com/performance/rules.html#js_bottom
スクリプトを一番下に置く
スクリプトによって引き起こされる問題は、それらが並列ダウンロードをブロックすることです。 HTTP/1.1仕様では、ブラウザはホスト名ごとに2つ以下のコンポーネントを同時にダウンロードすることを推奨しています。複数のホスト名から画像を提供している場合は、3つ以上のダウンロードを並行して実行できます。スクリプトがダウンロードされている間、ブラウザは異なるホスト名であっても他のダウンロードを開始しません。
ノンブロッキングスクリプトタグは、ほぼどこにでも配置できます。
<script src="script.js" async></script>
<script src="script.js" defer></script>
<script src="script.js" async defer></script>
async
scriptは、使用可能になると同時に非同期に実行されます。defer
スクリプトはドキュメントの解析が終了したときに実行されますasync defer
asyncがサポートされていない場合、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
-->
とは言っても、非同期スクリプトには次のような利点があります。
コールバックをサポートする外部スクリプトを使用することによって、実行順序の問題を回避することが可能です。多くのサードパーティのJavaScript APIは現在、ノンブロッキング実行をサポートしています。これは Google Maps APIを非同期でロードする例です 。
Yahoo!が推奨する標準的なアドバイス。 Exceptional Performanceチームは、<script>
タグをドキュメント本体の最後に配置して、ページのレンダリングをブロックしないようにします。
しかし、Google AnalyticsのJavaScriptファイルのロード時間についての この回答 で説明されているように、より良いパフォーマンスを提供する新しいアプローチがいくつかあります。
すばらしいスライド Steve Souders(クライアントサイドのパフォーマンスエキスパート)によると、
- 外部JavaScriptファイルを並行してロードするためのさまざまな手法
- 読み込み時間とページレンダリングへの影響
- ブラウザに表示される「進行中」のインジケータの種類(ステータスバーの「読み込み中」、砂時計のマウスカーソルなど)。
JQueryを使用している場合は、JavaScriptを最適な場所に配置し、$(document).ready()
を使用して、関数を実行する前に正しくロードされるようにします。
ちなみに、<head>
セクションにある私のスクリプトタグはすべて最もきれいな場所のようです。
XHTMLスクリプトがhead要素内以外の場所にあるかどうかを検証しません。 それはどこにでもあることがわかります。
JQueryのようなもので実行を延期することができるので、それがどこに配置されていても関係ありません(解析中のわずかなパフォーマンスのヒットを除く)。
<script src="myjs.js"></script>
</body>
scriptタグは、常にbody closeまたはHTMLの下部 fileの前に使用してください。
その後、js fileをロードする前に、ページのコンテンツを最初に見ることができます。
必要ならこれをチェックしてください: http://stevesouders.com/hpws/rule-js-bottom.php
これまでの(そして広く受け入れられている)答えは「一番下」です。その場合、何かが実行を開始する前にDOM全体がロードされていたはずです。
さまざまな理由で、page onloadイベントで意図的に実行を開始するために利用可能なプラクティスから始めて、反対者がいます。
2019年の最新のアプローチはES6モジュールタイプのスクリプトを使用することです 。
<script type="module" src="..."></script>
デフォルトでは、モジュールは非同期にロードされ防御されます。つまり、どこにでも配置でき、それらは並行してロードされ、ページのロードが完了したときに実行されます。
スクリプトとモジュールの違いは以下のとおりです。
https://stackoverflow.com/a/53821485/731548
スクリプトと比較したモジュールの実行について説明します。
https://developers.google.com/web/fundamentals/primers/modules#defer
サポートはここに示されています:
スクリプトとその使用法に応じて、(ページのロードとレンダリング時間に関して)最善の方法は、従来の<script>タグ自体を使用せずに、スクリプトのロードを非同期に動的にトリガーすることです。
いくつかの手法がありますが、最も簡単な方法は、window.onloadイベントが発生したときにdocument.createElement( "script")を使用することです。その後、ページ自体がレンダリングされたときにスクリプトが最初にロードされるので、ユーザーがページが表示されるのを待たなければならない時間に影響を与えません。
これは当然スクリプト自体がページのレンダリングに必要ではないことを必要とします。
詳しくは、Steve Souders(YSlowの作成者であるが現在はGoogleにある)による投稿 Coupling async scripts を参照してください。
最後にスクリプトを含めるのは、Webサイトのコンテンツ/スタイルを最初に表示する場合に主に使用されます。
頭にスクリプトを含めると、スクリプトが早くロードされ、Webサイト全体をロードする前に使用できます。
スクリプトが最後に入力された場合、検証はスタイルとデザイン全体をロードした後にのみ行われます。これは、応答の速いWebサイトには不適切です。
ページのスタイルを設定したり、ページ内のアクションを使用したりするために必要なスクリプト(ボタンをクリックするなど)を読み込んでいる場合は、それを一番上に配置することをお勧めします。あなたのスタイルが100%CSSで、あなたがボタンアクションのためのすべての代替オプションを持っているなら、あなたはそれを一番下に置くことができます。
あるいは、それが気にならない場合は、モーダルロードボックスを作成し、JavaScriptをページの一番下に配置し、スクリプトの最後の行がロードされたときにそれを消すことができます。これにより、スクリプトがロードされる前に、ユーザーがページ内でアクションを使用するのを防ぐことができます。また不適切なスタイリングも避けてください。
それでもIE <10でのサポートとパフォーマンスに関心がある場合は、必ずスクリプトタグをHTML本体の最後のタグにすることをお勧めします。そうすれば、DOMの残りの部分がロードされたことが確実にわかります。ブロックしたりレンダリングしたりすることはありません。
IE <10についてあまり気にしないのであれば、スクリプトをドキュメントの先頭に置き、defer
を使用してDOMがロードされた後にのみ実行されるようにします(<script type="text/javascript" src="path/to/script1.js" defer></script>
)。それでもコードをIE <10で動作させたい場合は、コードをwindow.onload
で囲むことを忘れないでください。
Webページの実行に依存すると思います。最初にJavaScriptをロードしないと表示したいページが正しく表示されない場合は、最初にJavaScriptファイルを含める必要があります。しかし、最初にJavaScriptファイルをダウンロードしなくてもWebページを表示またはレンダリングできる場合は、JavaScriptコードをページの下部に配置する必要があります。それは迅速なページロードをエミュレートするので、そしてユーザーの観点からはそれはそのページがより速くロードされているように思われるでしょう。
スクリプトは、DOMがロードされ実行されるまで、DOMロードをブロックします。
スクリプトを<body>
の最後に置くと、すべてのDOMがロードおよびレンダリングされる可能性があります(ページの表示が速くなります)。 <script>
は、これらすべてのDOM要素にアクセスできます。
一方、<body>
start以降の後に配置すると、スクリプトが実行されます(まだDOM要素はありません)。
あなたはjQueryをインクルードしています、つまりあなたが望むところならどこにでもそれを置くことができ、 .ready()
<script>
の参照の大部分は、<body>
の末尾に配置できます。
しかし、あなたのページに外部スクリプトを使っているアクティブなコンポーネントがあるなら、
その場合、それらの依存関係(jsファイル)はその前にくるべきです(理想的にはheadタグ内)。
HTMLドキュメントの最後に
実行時にブラウザへのHTMLドキュメントのロードに影響しないようにします。
<script>
タグを配置するのに最適な場所は</body>
タグを閉じる前です
また、jsファイルを外部にロードすることには、独自の利点がありますブラウザによってキャッシュされるのようにページのロード時間を短縮する、それHTMLコードとJavaScriptコードを分離およびコードベースの管理を改善。
しかし、最新のブラウザは、async
やdefer
のような外部の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をロードしている場合、両方が実行されますdefer
を使用します。defer
を使用してこの順序でロードされると、script1が最初に実行されることが保証され、async
の別のスクリプトに依存している場合は、属性なしでスクリプトを使用し、すべてのasync
スクリプトの上に配置します。