66257


**やりたいこと**

  * 目的1.ページ読み込み完了前に実行する(jQueryやグローバルナビゲーションなど)js読込
  * 目的2.ページ読み込み完了後に実行する(クリックしたら一番上までスクロールなど)js読込

* * *

**Q.下記組み合わせがあると思うのですが、やりたいことをそれぞれ実現するためにはどうすれば良いですか？**  
目的に応じて、それぞれ2つに分け、js読込を記述しようと考えています。

記述場所  
・`</head>`タグ直前  
・`</body>`タグ直前

記述方式  
・`<script>`  
・`<script async>`  
・`<script defer>`  
・`<script async defer>`

* * *

**現時点の案**

  * 目的1.`</head>`タグ直前に、`<script async>`を記述  
asyncにすると、jsはHTML読込と平行してダウンロードされ、HTML読込中断後実行される？

  * 目的2.`</body>`タグ直前に、`<script defer>`を記述  
deferにすると、jsはHTML読込と平行してダウンロードされ、HTML読込完了後実行される？  
asyncもdeferも、HTML読込と平行してダウンロードされるのであれば、`</body>`タグ直前ではなく、`</head>`タグ直前に記述する方が良いですか？


CC BY-SA 4.0
2020-03-04T13:38:19.613
63566
2020-05-04T06:48:11.373
2020-05-04T06:26:06.380
7997
7886
question
javascript html5
scriptタグのasyncとdeferプロパティの指定する手順


async, deferは利用時の制約がありますので、それに応じてどの順序でどこに記述するかある程度決定されます。  
これらのオプションを利用する場合、JavaScriptによるブラウザのFirst Paintのブロックを回避するために利用します。  
ただし、これらは正しく利用しないと機能要件を満たせない場合があるので、順を追って指定していきましょう。

## Step 1: bodyの最後でscriptを記述する

まずは機能要件を確実に担保するには、`</body>`の直前に`<script>`を記述することでしょう。

[code]

    <body>
      <script src="jquery.js"></script>
      <script src="file1.js"></script>
      <script src="file2.js"></script>
    </body>
    
[/code]

まずはこの形式を作ってください。

## Step 2: deferをつける

HTMLパーサーがscriptの記述箇所に到達したあと、JavaScriptのダウンロードが始まり、  
HTMLのパースが完了してから実行されます。つまり、`script`タグを`head`タグ内に記述すると`body`末尾につけるより早くJSのダウンロードが完了します。また、`defer`は定義された
**順番に実行** されます。

これらより、Step 1のコードは次のように書き換えることができます。

[code]

    <head>
      <script defer src="jquery.js"></script>
      <script defer src="file1.js"></script>
      <script defer src="file2.js"></script>
    </head>
    
[/code]

## Step 3: asyncをつける

`async`を付与可能なscriptタグには条件があります。

  * 読み込むJavaScriptが他のコードに依存していない場合
  * 機能的に先に読み込まれても問題ない場合

たとえば次のようなケースを考えます。

  * `jquery.js`: jQueryライブラリ
  * `file1.js`: 実装にjQueryを利用している
  * `file2.js`: 実装にjQueryを利用していない

このとき、`file1.js`は`jquery.js`に依存しているため`jquery.js`の読み込み後に実行する必要があります。  
すなわち、以下のように書くことができます。

[code]

    <head>
      <script defer src="jquery.js"></script>
      <script defer src="file1.js"></script>
      <script async src="file2.js"></script>
    </head>
    
[/code]

`file2.js`は排他的なコードであるため、`file1.js`や`jquery.js`よりも前に実行しても良い気がしますが、  
`file2.js`がダウンロード完了後にJavaScriptが即実行され、その間HTMLのパースが一時停止されます。仮にパースが再開されるまでの待機時間が長く、その後に`defer`の付いたscriptタグがパースされ、後者のダウンロード時間がHTMLパース完了より長い場合に時間的な損失が発生します（追記画像のPattern
2に該当します）。

すなわち、`defer`のあとに`async`のついたscriptタグを定義したほうが細かい損失を気にせずに済みます。

## 回答

今回の問に対する回答に移ります。

>   * 目的1.ページ読み込み完了前に実行する(jQueryやグローバルナビゲーションなど)js読込
>   * 目的2.ページ読み込み完了後に実行する(クリックしたら一番上までスクロールなど)js読込
>

これだけの条件であれば、Step
2の`defer`オプションをつけた`script`タグを`head`タグ末尾に入れる、までとなります。`async`オプションを付けるかどうかを判断するためには、ファイルの実行順序の依存関係の情報が必要です。

## 追記

[![async,
deferをつけたscriptがタグの動き](https://i.stack.imgur.com/1J8TF.png)](https://i.stack.imgur.com/1J8TF.png)


CC BY-SA 4.0
2020-05-03T16:29:05.973
66257
2020-05-04T06:48:11.373
2020-05-04T06:48:11.373
7997
7997
63566
answer