HTML の達人？async と defer で実力を証明せよ

[![表紙](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3967621/169c7788-38dc-ad9f-6e0f-b88176c06785.png)](https://leapcell.io/?lc_t=q_htmlasync)

すべての Web 開発者は HTML を熟知していると言うでしょう。しかし… `script` の `async` と `defer` の違いを本当に理解していますか？

これらは現代のフロントエンド Web アプリでよく使われますが、意外と見落とされがちです。

まず、HTML における `script` タグの 3 つの使い方をまとめます。詳細は後述します。

1. **デフォルト（順番に実行）**: `<script src='https://...'></script>`
2. **ダウンロード後すぐに実行**: `<script src='https://...' async></script>`
3. **ダウンロード後、最後に実行**: `<script src='https://...' defer></script>`

## script（デフォルト）

### 説明

ブラウザが HTML を解析しているとき、デフォルトの `script` タグを見つけると：

1. HTML の解析を一時停止する
2. 指定された JavaScript をダウンロードし、ダウンロード完了後すぐに実行する
3. 実行後、HTML の解析を再開する

以下のコードを見てみましょう：

```html
<html lang="zh">
  <head>
    <script>
      console.log('First script');
    </script>
    <script src="https://.../Chart.min.js"></script>
    <script src="https://.../moment.min.js"></script>
    <script src="https://.../vue.min.js"></script>
  </head>
  <body>
    ウェブページの内容 1
  </body>
</html>
```

実行順序は以下のようになります：

1. `console.log("First script");` を実行
2. `Chart.min.js` をダウンロード＆実行
3. `moment.min.js` をダウンロード＆実行
4. `vue.min.js` をダウンロード＆実行
5. ウェブページの内容を表示

### 注意点

デフォルトの `script` タグは **順番に実行** されるため、処理が長いスクリプトがあると後続のスクリプトが待たされ、HTML の解析も止まるため、**白画面（何も表示されない状態）が発生する可能性があります**。

## script async

### 説明

HTML 解析中に `script async` を含むタグを見つけると：

1. HTML の解析を続けながら **非同期で JavaScript をダウンロード** する
2. ダウンロードが完了すると、**即座に実行** され、HTML の解析が一時停止する
3. スクリプト実行後、HTML の解析を再開する

以下のコードを見てみましょう：

```html
<html lang="zh">
  <head>
    <script>
      console.log('First script');
    </script>
    <script async src="https://.../Chart.min.js"></script>
    <script async src="https://.../moment.min.js"></script>
    <script async src="https://.../vue.min.js"></script>
  </head>
  <body>
    ウェブページの内容 2
  </body>
</html>
```

実行順序は以下のようになります：

1. `console.log("First script");` を実行
2. `Chart.min.js`、`moment.min.js`、`vue.min.js` を **非同期でダウンロード**（HTML の解析は継続）
3. 各スクリプトのダウンロードが完了した順に即座に実行（この間 HTML の解析は一時停止）
4. HTML の解析を再開

### 注意点

- `async` のスクリプトは **実行時に HTML の解析をブロックする** ため、HTML の構造が単純な場合、**スクリプトの実行前にページが完全に表示される可能性が高い**。
- HTML の解析に時間がかかる場合、途中でスクリプトの実行が割り込むことがある。

## script defer

### 説明

HTML 解析中に `script defer` を含むタグを見つけると：

1. HTML の解析を続けながら **非同期で JavaScript をダウンロード** する
2. **ダウンロード完了後もすぐには実行せず**、HTML の解析が完了するまで待つ
3. HTML の解析が終わった後、**順番にスクリプトを実行する**

以下のコードを見てみましょう：

```html
<html lang="zh">
  <head>
    <script>
      console.log('First script');
    </script>
    <script defer src="https://.../Chart.min.js"></script>
    <script defer src="https://.../moment.min.js"></script>
    <script defer src="https://.../vue.min.js"></script>
  </head>
  <body>
    ウェブページの内容 3
  </body>
</html>
```

実行順序は以下のようになります：

1. `console.log("First script");` を実行
2. `Chart.min.js`、`moment.min.js`、`vue.min.js` を **非同期でダウンロード**（HTML の解析は継続）
3. **HTML の解析が完了後にスクリプトを順番に実行**
4. ウェブページの内容を表示

### 注意点

- `defer` がついた複数のスクリプトは **並行してダウンロードされる**。
- ただし、ダウンロードの順番に関係なく **HTML の記述順で実行** される。

## 混合使用

実際の開発では、`async` と `defer` を組み合わせて使用することがあります。

```html
<html lang="zh">
  <head>
    <script>
      console.log('First script');
    </script>
    <script defer src="https://.../Chart.min.js"></script>
    <script async src="https://.../moment.min.js"></script>
    <script defer src="https://.../vue.min.js"></script>
  </head>
  <body>
    ウェブページの内容 4
  </body>
</html>
```

実行順序は以下のようになります：

1. `console.log("First script");` を実行
2. `Chart.min.js`、`moment.min.js`、`vue.min.js` を **非同期でダウンロード**
3. `moment.min.js` のダウンロード完了後すぐに実行
4. `Chart.min.js` と `vue.min.js` は **HTML の解析完了後に実行**

## まとめ

| タグ             | HTML の解析                                                        | 実行順                                |
| ---------------- | ------------------------------------------------------------------ | ------------------------------------- |
| `<script>`       | **ブロック**                                                       | **記述順に実行**                      |
| `<script async>` | **ブロックしない**（ダウンロード時）<br>**ブロックする**（実行時） | **ダウンロード完了順**（順不同）      |
| `<script defer>` | **ブロックしない**                                                 | **記述順に実行（HTML の解析完了後）** |

- **独立したスクリプト** なら `async`（ただし HTML の解析が一時停止する可能性あり）
- **依存関係のあるスクリプト** なら `defer`
- **`async` と `defer` が両方指定された場合、`async` が優先される**

---

### [私たちはLeapcell、Node.jsプロジェクトのホスティングの最適解です。](https://leapcell.io/?lc_t=q_htmlasync)

[![Leapcell](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3967621/e7b79df9-8d87-6094-4781-391f25e284af.png)](https://leapcell.io/?lc_t=q_htmlasync)

[Leapcell](https://leapcell.io/?lc_t=q_htmlasync)は、Webホスティング、非同期タスク、Redis向けの次世代サーバーレスプラットフォームです：

**複数言語サポート**

- Node.js、Python、Go、Rustで開発できます。

**無制限のプロジェクトデプロイ**

- 使用量に応じて料金を支払い、リクエストがなければ料金は発生しません。

**比類のないコスト効率**

- 使用量に応じた支払い、アイドル時間は課金されません。
- 例: $25で6.94Mリクエスト、平均応答時間60ms。

**洗練された開発者体験**

- 直感的なUIで簡単に設定できます。
- 完全自動化されたCI/CDパイプラインとGitOps統合。
- 実行可能なインサイトのためのリアルタイムのメトリクスとログ。

**簡単なスケーラビリティと高パフォーマンス**

- 高い同時実行性を容易に処理するためのオートスケーリング。
- ゼロ運用オーバーヘッド — 構築に集中できます。

[ドキュメントで詳細を確認！](https://docs.leapcell.io/)

[![Try Leapcell](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3967621/6d02e099-fd7b-57d0-7b7f-5067c3a2b72b.png)](https://leapcell.io/?lc_t=q_htmlasync)

Xでフォローする：[@LeapcellHQ](https://x.com/LeapcellHQ)

---

[ブログでこの記事を読む](https://leapcell.io/blog/async-and-defer-in-html-script-tags)