ブラウザが<script>
タグのあるWebサイトをロードすると、次のようになります。
- HTMLページを取得します(例:index.html)
- HTMLの解析を開始します
- パーサーは
<script>
、外部スクリプトファイルを参照するタグを検出しました。
- ブラウザがスクリプトファイルを要求します。その間、パーサーはページ上の他のHTMLのブロックと解析を停止します。
- しばらくすると、スクリプトがダウンロードされ、その後実行されます。
- パーサーは、残りのHTMLドキュメントの解析を続行します。
手順4は、ユーザーエクスペリエンスを低下させます。すべてのスクリプトをダウンロードするまで、Webサイトは基本的にロードを停止します。ユーザーが嫌いなことが1つあるとしたら、それはWebサイトがロードされるのを待っています。
なぜこれが起こるのですか?
スクリプトは、独自のHTMLを介して、document.write()
または他のDOM操作を挿入できます。これは、スクリプトがダウンロードされて実行されるまで、パーサーはドキュメントの残りを安全に解析できるようになるまで待機する必要があることを意味します。結局のところ、スクリプトはドキュメントに独自のHTMLを挿入できたはずです。
ただし、ほとんどのJavaScript開発者は、ドキュメントの読み込み中にDOM を操作しなくなりました。代わりに、ドキュメントがロードされるまで待ってから変更します。例えば:
<!-- index.html -->
<html>
<head>
<title>My Page</title>
<script 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 src="path/to/script1.js" async></script>
<script src="path/to/script2.js" async></script>
async属性を持つスクリプトは非同期で実行されます。つまり、スクリプトはダウンロードされるとすぐに実行され、その間ブラウザはブロックされません。
これは、スクリプト1の前にスクリプト2がダウンロードされて実行される可能性があることを意味します。
http://caniuse.com/#feat=script-asyncによると、すべてのブラウザの97.78%がこれをサポートしています。
延期する
<script src="path/to/script1.js" defer></script>
<script src="path/to/script2.js" defer></script>
defer属性を持つスクリプトは順番に実行されます(つまり、最初にスクリプト1、次にスクリプト2)。これもブラウザをブロックしません。
非同期スクリプトとは異なり、遅延スクリプトは、ドキュメント全体が読み込まれた後にのみ実行されます。
http://caniuse.com/#feat=script-deferによると、すべてのブラウザの97.79%がこれをサポートしています。98.06%が少なくとも部分的にサポートしています。
ブラウザーの互換性に関する重要な注意:状況によっては、IE <= 9で遅延スクリプトが順不同で実行される場合があります。あなたはこれらのブラウザをサポートする必要がある場合は、お読みください。この最初の!
結論
現在の最新技術では、スクリプトを<head>
タグに入れ、async
or defer
属性を使用しています。これにより、ブラウザーをブロックすることなく、スクリプトをできるだけ早くダウンロードできます。
良い点は、これらの属性をサポートしていないブラウザの2%でWebサイトが正しくロードされ、他の98%が高速化することです。