【入門編】 JavaScriptの実行タイミング制御(defer, async, type=module) – Webブラウザの仕組み実践ガイド

こんにちは!Web制作やJavaScriptの勉強、毎日お疲れ様です。

画面に文字や画像を表示させるためにHTMLを書いて、動きをつけるためにJavaScriptを読み込ませる……。最初は「よし、動いた!」と感動するのですが、少し慣れてくるとこんな壁にぶつかりませんか?

「あれ? なんかページが表示される瞬間に、画面がカクついたり、真っ白な時間が長かったりするぞ……?」

そうなんです。私たちが何気なく書いている `` と書いたとしましょう。
ブラウザが上から順にHTMLを読んでいって、このタグに出会った瞬間、ブラウザは「うわっ、大変だ!JavaScriptをダウンロードして、今すぐ実行しなきゃ!」と、それまでの作業をピタッと止めてしまいます。

レストランの例えで言うなら、料理人がスープを作っている途中で、突然配送員が「重要なお知らせです!」と飛び込んでききて、料理人がその場でそれを読まされるようなものです。配送員が読み終わるまで、スープ作りは完全にストップしてしまいます。

これが、HTMLのパース(解析)がブロックされる瞬間です。JavaScriptが大きければ大きいほど、ユーザーの画面には「真っ白な画面」が長く映し出されることになり、「このサイト、重いな……」と離脱されてしまう原因になるのです。

「じゃあ、どうすればいいの!?」ですよね。
その救世主こそが、今回主役の `defer` と `async` なんです。

---

2. `defer`:お行儀よく「後でまとめて読む」お利口さん

まずは `defer`(ディファー=遅延させる) からご紹介します。

`defer` は、JavaScriptの読み込みを裏側でこっそり進めつつ、「HTMLの解析(お仕事)がぜーんぶ終わってから、最後に実行してね」とブラウザにお願いする属性です。


日常の例え:届いた荷物は最後に開封する

オンラインショッピングで次々と荷物(HTMLのパーツ)が届いている最中に、わざわざ作業を止めてダンボールをカッターで開けて中身を確認したりしませんよね?
まずは届いた荷物を部屋の隅にどんどん積み上げて(裏側でスクリプトをダウンロードして)、家全体の片付け(HTMLのパース)が終わったあとに、「さて、中身を開けようか」と一気に開封する(スクリプトを実行する)。これが `defer` の動きです。

ここが嬉しいポイント:

  • HTMLのパースを邪魔しないので、画面の表示速度(体感速度)がグッと上がります。
  • 複数の `defer` 付きスクリプトがある場合、書いた順番通りに実行されるため、ライブラリとその依存関係があるコード(例:jQueryを先に読み込んで、その後にプラグインを動かすなど)でも安心して使えます。

迷ったら、とりあえずスクリプトは `defer` をつけておけば大きな失敗はありません。「困ったときの優等生」と覚えておいてくださいね。

---

3. `async`:マイペースに「準備ができたら即実行」の自由人

続いて `async`(エイシンク=非同期) です。

`async` も `defer` と同じように、裏側でJavaScriptをダウンロードしてくれますが、決定的な違いがあります。それは、「ダウンロードが終わった瞬間、HTMLの解析を無理やり止めてでも、その場で実行する」というマイペースさです。


日常の例え:郵便受けに届いた「緊急の回覧板」

家事をしている最中に郵便受けに「回覧板」が入っているのを見つけたとします。
`async` は、「あ、回覧板だ。今やっている掃除をちょっと中断して、その場で内容を読み上げちゃうね!」という動きです。

どんなときに使うの?
他のHTMLの要素や、他のJavaScriptに依存しない、完全に独立したスクリプトに向いています。
代表例が「アクセス解析ツール(Google Analyticsなど)」や「広告タグ」です。これらは「ページの他の部分がどうなっていようと、とにかく早く読み込んで動いてくれればいい」ものなので、`async` が最適解になります。

逆に、DOM要素(ボタンやテキスト)を操作する自作のJavaScriptに `async` をつけてしまうと、「まだHTMLのパーツが準備できてないよ!」というタイミングでスクリプトが暴走してエラー(`Uncaught TypeError` など)を引き起こすことがあるので注意してくださいね。
「あ、エラーが出ちゃった!」というときは、`async` を `defer` に変えてみるとスッと解決することがよくありますよ。

---

4. 現代の標準! `type="module"` のスマートな秘密

さて、近年のモダンなWeb開発では、ES Modules(ESM)という仕組みを使って、JavaScriptファイルを `import` / `export` で分割して書くのが当たり前になりました。

ここで書く、`type="module"` です。


実はこの `type="module"`、標準で `defer` と全く同じ遅延実行の性質 を持っています。
つまり、ブラウザは自動的に「お、モジュールだな。じゃあHTMLの解析を止めずに、裏側でダウンロードして、解析が終わってから実行しよう」と判断してくれます。わざわざ `defer` と書き添える必要はありません(書いても動きますが、重複します)。

モジュールがレンダリングに与える影響

ES Modulesは、他のファイルを `import` する依存関係のツリーをブラウザが事前にしっかりと組み立ててから実行します。そのため、安全性が高く、スコープ(変数の有効範囲)も綺麗に保たれます。

実務においては、特別な理由がない限り、現代のフロントエンド開発ではJavaScriptをモジュールとして読み込み、ブラウザのレンダリングパイプラインをスムーズに保つのが王道のスタイルになっています。

---

まとめ:今日から使える「scriptタグの選び方」

ここまで、ブラウザの頑張りと、それを助ける属性たちを見てきました。最後に、実務で迷ったときにパッと見返せる「選び方のチートシート」を置いておきますね。

1. 基本のキ(迷ったらこれ)

  • 自作のアプリケ―ションコードやライブラリ群
  • 👉 `` (または `type="module"`)

2. 独立した外部ツール(解析・広告など)

  • 他の要素に依存せず、最速で読み込ませたいもの
  • 👉 ``

3. どうしてもHTMLのパースをその場で止めたい場合(ごく稀)

  • スクリプトの読み込み順が絶対で、かつHTMLの構築と完全に同期させたい古い仕組みなど
  • 👉 属性なし( `` ) ※ただし現代のWeb制作ではほぼ使いません。

Webブラウザは、私たちが書いたコードを文句も言えず、一生懸命、かつ賢く解釈して画面を描き出そうとしています。そのブラウザの性質をちょっとだけ理解して、適切な手助け(属性の付与)をしてあげることで、ユーザーにとって「サクサク動く、心地よいWebサイト」が作れるようになります。

もしコードを書いていて「あれ、動かないな」「画面が変だな」と思ったら、今日のこの記事を思い出してみてください。「あ、ブラウザが処理の順番で困ってるのかもな」と優しく原因を探れるはずです。

あなたのWeb開発の旅が、もっと楽しく、ワクワクするものでありますように!一緒に一歩ずつ進んでいきましょうね。

コメント

タイトルとURLをコピーしました