ITエンジニア日記 ~NO SKILL, NO LIFE~

学んだ技術や、気になることをアウトプットしていきます。プログラミング, インフラ, etc...

【JavaScript】scriptタグのdefer属性とasync属性

HTMLのscriptタグについて、defer属性とasync属性の勉強をしました。

1. デフォルト(defer/asyncを付けない場合)

<!DOCTYPE html>
<html lang="ja">
  <head>
    <meta charset="utf-8">
    <title>TEST HTML</title>
  </head>
  <script src="script1.js"></script>
  <script src="script2.js"></script>
  <script src="script3.js"></script>
  <body>
    <p>test</p>
  </body>
</html>

WebブラウザがHTMLを解析(パース)する際、HTMLを上から順に解析していきます。
上記のコードでは、headタグを解析した後に、scriptタグのJavaScriptファイルを

  1. script1.js
  2. script2.js
  3. script3.js

の順に読み込みます。
このとき、JavaScriptファイルを読み込んで、実行し終わるまではHTMLの解析はストップします。
JavaScriptの読み込み・解析が完了したら、HTMLの解析が再開されbodyタグから解析されます。

f:id:masakiXX0:20200113231430j:plain
HTMLの解析とJavaScriptの読み込み・実行【default】

2. defer

  <script src="script1.js" defer></script>
  <script src="script2.js" defer></script>
  <script src="script3.js" defer></script>

defer属性を付けると、scriptタグが出てきたらJavaScriptファイルを非同期に読み込みます。このとき、HTMLの解析はストップしません。

JavaScriptファイルの読み込みが完了しても実行はされず、HTMLの解析が続行されます。

HTMLの解析が完了したら、scriptタグの書かれた順番に上から実行されます。

f:id:masakiXX0:20200113230015j:plain
HTMLの解析とJavaScriptの読み込み・実行【defer】

2.1. deferの特徴

  • JavaScriptの読み込み時にHTMLの解析をストップさせない
  • scriptタグの順番に実行される
  • スクリプトが実行されるのはHTMLの解析が完了してから

3. async

  <script src="script1.js" async></script>
  <script src="script2.js" async></script>
  <script src="script3.js" async></script>

defer属性を付けると、scriptタグが出てきたらJavaScriptファイルを非同期に読み込みます。このとき、HTMLの解析はストップしません。

JavaScriptファイルの読み込みが完了したら、JavaScriptが実行されます。このときJavaScriptの実行は、読み込みが完了した順に行われます。
よって、scriptタグが書かれた順番通りにJavaScriptが実行されない可能性があります。

JavaScriptの読み込み実行が完了したら、HTMLの解析が再開されます。

f:id:masakiXX0:20200113230632j:plain
HTMLの解析とJavaScriptの読み込み・実行【async】

3.1. asyncの特徴

  • JavaScriptの読み込み時にHTMLの解析をストップさせない
  • scriptタグの順番に実行されない可能性がある
  • スクリプトが実行されるのは、JavaScriptファイルの読み込みが完了した直後

4. deferとasyncの使い分け

deferもasyncも付けない場合、JavaScriptの読み込み時にHTMLの解析がストップしてしまうため、パフォーマンスが悪くなるそうです。
scriptタグを使用するときは、defer属性かasync属性を付けてあげましょう。

deferとasyncの使い分けとしては、複数のJavaScriptファイルを読み込むときに、
 スクリプト間の依存関係がない場合は「async」
 スクリプト間の依存関係がある場合は「defer」
とするのがよいそうです。

まとめ

scriptタグのdefer属性とasync属性についてまとめてみました。

参考