2026年5月20日
2026年5月20日
WordPressのJavaScriptを最小化・遅延読み込みする方法
はじめに
JavaScriptはCSSと並んでレンダリングブロックの主な原因です。defer や async 属性を付与することでHTMLのパースをブロックしなくなり、PageSpeed InsightsのTBT(Total Blocking Time)とFID/INPスコアを改善できます。
症状・原因
- PageSpeed Insightsで「レンダリングブロックリソースの除外」を指摘される
- TBT(Total Blocking Time)やINPのスコアが低い
- プラグインのJSがすべてのページで読み込まれている
- jQueryが不要なのにheadで読み込まれている
解決手順
ステップ1:WordPress 6.3以降のdefer/async対応を使う
// functions.php
// WordPress 6.3以降: strategy パラメータで defer/async を指定
function mytheme_enqueue_scripts(): void {
// defer: DOMが構築された後に実行(順序保証あり)
wp_enqueue_script(
'mytheme-main',
get_template_directory_uri() . '/assets/js/main.min.js',
[], // 依存なし(jQueryに依存しない場合)
filemtime(get_template_directory() . '/assets/js/main.min.js'),
['strategy' => 'defer'] // WordPress 6.3以降の新記法
);
// async: 読み込み完了次第即実行(順序保証なし)
wp_enqueue_script(
'mytheme-analytics',
get_template_directory_uri() . '/assets/js/analytics.min.js',
[],
'1.0.0',
['strategy' => 'async', 'in_footer' => true]
);
}
add_action('wp_enqueue_scripts', 'mytheme_enqueue_scripts');
ステップ2:WordPress 6.2以前でdefer/asyncを追加する
// functions.php
// script_loader_tag フィルターで defer/async を付与
function mytheme_add_script_attributes(string $tag, string $handle): string {
$defer_scripts = ['mytheme-main', 'mytheme-slider'];
$async_scripts = ['mytheme-analytics', 'mytheme-gtm'];
if (in_array($handle, $defer_scripts, true)) {
return str_replace('<script ', '<script defer ', $tag);
}
if (in_array($handle, $async_scripts, true)) {
return str_replace('<script ', '<script async ', $tag);
}
return $tag;
}
add_filter('script_loader_tag', 'mytheme_add_script_attributes', 10, 2);
ステップ3:不要なJavaScriptを削除する
// functions.php
function mytheme_dequeue_unused_scripts(): void {
// jQueryをフロントエンドで無効化(独自JSがVanillaの場合)
// ※ プラグインがjQueryに依存している場合は削除しないこと
if (!is_admin() && !is_user_logged_in()) {
// wp_dequeue_script('jquery'); // 慎重に判断
}
// Emojiスクリプトを削除(不要な場合)
remove_action('wp_head', 'print_emoji_detection_script', 7);
remove_action('wp_print_styles', 'print_emoji_styles');
wp_dequeue_script('wp-emoji-release');
// Contact Form 7のJSをフォームページ以外で無効化
if (!is_page('contact')) {
wp_dequeue_script('contact-form-7');
}
// oEmbedスクリプトを削除(埋め込みを使わない場合)
wp_deregister_script('wp-embed');
}
add_action('wp_enqueue_scripts', 'mytheme_dequeue_unused_scripts', 100);
ステップ4:TerserでJavaScriptをMinifyする
// package.json
{
"scripts": {
"build:js": "terser src/js/main.js -o assets/js/main.min.js --compress --mangle",
"build:js:all": "find src/js -name '*.js' -exec sh -c 'terser {} -o assets/js/$(basename {} .js).min.js --compress --mangle' \\;",
"watch:js": "nodemon --watch src/js --ext js --exec 'npm run build:js'"
},
"devDependencies": {
"terser": "^5.0.0",
"nodemon": "^3.0.0"
}
}
// webpack.config.js(Webpackを使う場合)
const TerserPlugin = require('terser-webpack-plugin');
module.exports = {
mode: 'production',
entry: './src/js/main.js',
output: {
filename: 'main.min.js',
path: __dirname + '/assets/js',
},
optimization: {
minimizer: [
new TerserPlugin({
terserOptions: {
compress: { drop_console: true }, // console.logを削除
mangle: true,
},
}),
],
},
};
ステップ5:jQueryを最適化する
// functions.php
// jQueryをCDNから読み込んでキャッシュヒット率を上げる
function mytheme_use_cdn_jquery(): void {
if (is_admin()) {
return;
}
wp_deregister_script('jquery');
wp_register_script(
'jquery',
'https://code.jquery.com/jquery-3.7.1.min.js',
[],
'3.7.1',
['strategy' => 'defer']
);
wp_enqueue_script('jquery');
}
// add_action('wp_enqueue_scripts', 'mytheme_use_cdn_jquery');
// ※ SRIハッシュの設定も検討すること
// jQueryをフッターに移動(ヘッダーでのブロックを防ぐ)
function mytheme_move_jquery_to_footer(): void {
if (!is_admin()) {
wp_scripts()->add_data('jquery', 'group', 1); // フッターに移動
wp_scripts()->add_data('jquery-core', 'group', 1);
wp_scripts()->add_data('jquery-migrate', 'group', 1);
}
}
add_action('wp_enqueue_scripts', 'mytheme_move_jquery_to_footer');
注意事項
deferとasyncの違いを理解してください。deferはDOMが準備できてから実行・順序保証あり。asyncはダウンロード完了次第即実行・順序保証なし。jQueryに依存するスクリプトはasyncにするとjQueryの読み込み前に実行される可能性があります- jQueryを完全に削除する前に、使用しているすべてのプラグインがjQueryに依存していないか確認してください
- CDNからjQueryを読み込む場合は、CDNが障害を起こした際のフォールバックも検討してください
まとめ
WordPress 6.3以降は wp_enqueue_script の第5引数に ['strategy' => 'defer'] を渡すだけでdeferが付与されます。古いバージョンは script_loader_tag フィルターで対応します。不要なEmoji・oEmbedスクリプトは削除し、TerserでMinifyしたファイルを filemtime でバージョン管理します。