JavaScriptを外部ファイルとして読み込むとき、何気なく次のようなコードを書いていないでしょうか。
<script src="script.js"></script>
もちろん、この書き方でもJavaScriptは読み込まれます。
ただし、読み込む場所やファイルの内容によっては、ページの表示が遅くなったり、HTML要素がまだ存在しないタイミングでJavaScriptが実行されてエラーになったりすることがあります。
そこで使われるのが、async と defer です。どちらもJavaScriptの読み込みを効率化するための属性ですが、動き方はかなり違います。
この記事では、JavaScriptのasyncとdeferの違い、使い分け、WordPressサイトでの注意点、PageSpeed Insights改善との関係をわかりやすく解説します。
JavaScriptの読み込みが表示速度に影響する理由
HTMLは、上から順番に読み込まれていきます。
その途中で通常のscriptタグが出てくると、ブラウザはHTMLの解析を一時停止し、JavaScriptファイルを取得して実行します。
<head>
<script src="script.js"></script>
</head>
この場合、JavaScriptの読み込みや実行が終わるまで、HTMLの解析が止まることがあります。
その結果、以下のような問題が起こる可能性があります。
- ページの表示開始が遅くなる
- ファーストビューの描画が遅れる
- DOM要素が存在しない状態でJavaScriptが実行される
- PageSpeed Insightsで改善項目として指摘される
特に、ファーストビューに関係ないJavaScriptを早い段階で読み込んでいると、表示速度に悪影響が出やすくなります。
asyncとは
asyncは、JavaScriptファイルをHTML解析と並行してダウンロードし、ダウンロードが完了したタイミングですぐ実行する属性です。
<script src="analytics.js" async></script>
特徴は次の通りです。
- HTML解析と並行してJavaScriptをダウンロードする
- ダウンロードが終わったらすぐ実行される
- 実行順は保証されない
- DOMContentLoadedを待たない
- DOM操作を行うスクリプトには注意が必要
つまり、asyncは「読み込み終わったらすぐ実行していいJavaScript」に向いています。
asyncに向いているスクリプト
asyncに向いているのは、他のスクリプトやDOM要素への依存が少ないものです。
- アクセス解析タグ
- 広告タグ
- 外部サービスの計測タグ
- 単独で動作する第三者スクリプト
たとえば、Google Analyticsや広告関連のタグでasyncが使われることがあります。
ただし、他の処理に依存するJavaScriptや、HTML要素を操作するJavaScriptには向いていない場合があります。
deferとは
deferは、JavaScriptファイルをHTML解析と並行してダウンロードし、HTMLの解析が終わってから実行する属性です。
<script src="main.js" defer></script>
特徴は次の通りです。
- HTML解析と並行してJavaScriptをダウンロードする
- HTML解析が終わってから実行される
- 複数のdefer付きscriptは記述順に実行される
- DOM操作を行うスクリプトと相性がよい
- DOMContentLoadedの直前に実行される
deferは、通常のサイト制作ではかなり使いやすい属性です。
HTMLの読み込みを邪魔しにくく、DOMが準備された状態で実行されるため、メニュー、アコーディオン、スライダー、フォーム制御などにも使いやすいです。
asyncとdeferの違い
asyncとdeferの違いを表にすると、次のようになります。
| 項目 | async | defer |
|---|---|---|
| ダウンロード | HTML解析と並行 | HTML解析と並行 |
| 実行タイミング | 読み込み完了後すぐ | HTML解析完了後 |
| 実行順 | 保証されない | 記述順に実行 |
| DOM操作 | 注意が必要 | 比較的向いている |
| 向いている用途 | 解析・広告など独立した処理 | サイト本体のJavaScript |
迷った場合は、サイト本体のJavaScriptにはdeferを使う方が安全です。
通常のscript、async、deferの違いをコードで比較
通常のscript
<script src="main.js"></script>
HTML解析の途中で読み込みと実行が行われます。
配置場所によっては、ページ表示やDOM操作に影響します。
async
<script src="analytics.js" async></script>
HTML解析と並行して読み込み、読み込みが終わったらすぐ実行します。
実行順が重要なスクリプトには不向きです。
defer
<script src="main.js" defer></script>
HTML解析と並行して読み込み、HTML解析が終わってから実行します。
複数のスクリプトがある場合も、記述順に実行されます。
asyncを使うときの注意点
asyncは便利ですが、使い方を間違えると不具合の原因になります。
特に注意したいのは、以下のようなケースです。
- jQuery本体より先にjQuery依存スクリプトが実行される
- DOM要素がまだ存在しない状態で処理が走る
- 複数のJavaScriptの実行順が前後する
- スライダーやメニューが動かなくなる
たとえば、次のような指定は危険です。
<script src="jquery.js" async></script>
<script src="custom.js" async></script>
この場合、custom.jsがjquery.jsより先に実行される可能性があります。custom.jsがjQueryに依存している場合、エラーになるので注意しましょう。
deferを使うときの注意点
deferは扱いやすいですが、何でも付ければよいわけではありません。
次の点には注意しましょう。
- インラインスクリプトには基本的に使わない
- 古い外部スクリプトで動作前提が違う場合がある
- 広告タグや解析タグは提供元の推奨コードを確認する
- WordPressプラグインが出力するスクリプトを無理に変更しない
特にWordPressでは、テーマやプラグインがJavaScriptを出力しています。すべてに一括でdeferを付けると、一部の機能が動かなくなることがあります。
WordPressでasyncやdeferを使う場合
WordPressでは、wp_enqueue_script()を使ってJavaScriptを読み込むのが基本です。テーマ内で直接scriptタグを書くより、WordPressの仕組みに合わせた方が管理しやすくなります。
たとえば、テーマのJavaScriptを読み込む場合は以下のようにします。
function my_theme_scripts() {
wp_enqueue_script(
'theme-main',
get_template_directory_uri() . '/js/main.js',
array(),
'1.0.0',
true
);
}
add_action('wp_enqueue_scripts', 'my_theme_scripts');
最後のtrueは、フッター側に読み込む指定です。
最近のWordPressでは、スクリプト読み込み時に属性を指定する方法も用意されています。テーマやWordPressのバージョンに合わせて、deferやasyncを適切に付けるとよいです。
ただし、すべてのスクリプトへ機械的に付けるのはおすすめしません。
PageSpeed Insights対策としての考え方
PageSpeed Insightsでは、JavaScriptの読み込みや実行が表示速度に影響している場合があります。特に、以下のようなチェックに関係することがあります。
- レンダリングを妨げるリソースの除外
- 未使用のJavaScriptの削減
- メインスレッド作業の短縮
- LCPの改善
ただし、asyncやdeferを付ければ必ずスコアが上がるわけではありません。重要なのは、以下のように整理することです。
- ファーストビューに不要なJavaScriptは遅らせる
- 依存関係があるJavaScriptは実行順を守る
- 不要なプラグインのスクリプトを読み込まない
- 広告・解析タグは提供元の推奨方法を確認する
- 変更後は実機で動作確認する
表示速度を改善するには、属性の追加だけでなく、JavaScriptそのものを減らすことも大切です。
asyncとdeferの使い分けまとめ
基本的な使い分けは次の通りです。
| スクリプトの種類 | おすすめ |
|---|---|
| アクセス解析 | async |
| 広告タグ | 提供元の推奨に従う |
| DOM操作を行う自作JS | defer |
| jQuery依存のJS | deferまたはフッター読み込み |
| 他のJSに依存しない外部タグ | async |
迷った場合は、サイト本体のJavaScriptにはdefer、独立した解析タグにはasyncと考えると分かりやすいです。
まとめ
asyncとdeferは、どちらもJavaScriptの読み込みを効率化するための属性です。
ただし、動き方は違います。
- asyncは読み込み完了後すぐ実行される
- deferはHTML解析完了後に実行される
- asyncは実行順が保証されない
- deferは記述順に実行される
- DOM操作を行う自作JavaScriptにはdeferが使いやすい
JavaScriptの読み込みは、ページの表示速度や動作安定性に関わります。特にWordPressでは、テーマ・プラグイン・広告・解析タグなど、複数のJavaScriptが読み込まれがちです。
何でも一括で遅延すればよいわけではないので、スクリプトの役割ごとにasyncとdeferを使い分けることを意識して使ってみてください。