2023年6月1日

スクリプト: async, defer

最近の web サイトでは、スクリプトは HTML よりも “重い” ことがしばしばです: ダウンロードサイズはより大きく、処理時間も長くなります。

ブラウザが HTML をロードし、<script>...</script> タグに遭遇すると、DOM の構築を続けることはできません。すぐにスクリプトを実行する必要があります。外部スクリプト <script src="..."></script> についても同じです: ブラウザはスクリプトをダウンロードし、それを実行するまで待つ必要があり、その後にページの残り部分の処理をすることになります。

これは2つの重要な問題につながります:

  1. スクリプトは、それ以降の DOM要素は認識することができないため、ハンドラーを追加したりすることはできません。
  2. ページの先頭に重いスクリプトがあると、“ページをブロック” します。利用者はそれがダウンロードされ実行されるまでページコンテンツを見ることができません:
<p>...content before script...</p>

<script src="https://javascript.info/article/script-async-defer/long.js?speed=1"></script>

<!-- スクリプトがロードされるまで表示されません -->
<p>...content after script...</p>

回避策はいくつかあります。例えば、ページの末尾にスクリプトを置きます。すると要素を表示でき、ページコンテンツの表示をブロックしません:

<body>
  ...all content is above the script...

  <script src="https://javascript.info/article/script-async-defer/long.js?speed=1"></script>
</body>

ですが、この方法は完璧には程遠いです。例えば、ブラウザが完全なHTMLドキュメントをダウンロードした後にのみスクリプトに気づき(、ダウロードが開始でき)ます。HTML ドキュメントが長いと、かなりの遅延になる可能性があります。

このようなことは、十分に早い接続を使用している人々には見えませんが、世界中の多くの人は依然として低速のインターネットを利用しており、完璧とはほど遠いモバイルインターネット接続を使用しています。

幸いなことに、この問題を解決する2つの <script> 属性があります: deferasync です。

defer

defer 属性はブラウザにスクリプトを待たないよう指示します。代わりに、ブラウザは HTML の処理を継続し、DOM を構築します。スクリプトは “バックグラウンド” でロードされ、DOM が完全に構築されたときに実行されます。

これは上記と同じ例ですが、defer を指定しています:

<p>...content before script...</p>

<script defer src="https://javascript.info/article/script-async-defer/long.js?speed=1"></script>

<!-- すぐに表示されます -->
<p>...content after script...</p>