ページの初回描画が遅いと感じたら、最初に疑うべきは「レンダリングをブロックする JavaScript」です。ブラウザはデフォルトで <script>
に遭遇すると HTML の解析と描画を止め、スクリプトの取得と実行を待ちます。WordPress では、不要なスクリプトの読み込み停止、フッターへの移動、defer
や async
の付与でブロッキングを避けるのが定番です。以下では、テーマの functions.php
だけで実践できる手順を、影響が少ない順に解説します。
まずは「フッターへ移動」でブロッキングを回避する
多くのテーマやプラグインはヘッダーでスクリプトを出力します。可能な限りフッターに移せば、HTML と CSS が先に描画され、体感速度が上がります。自作・テーマ内の enqueue は第五引数を true
にしてフッターへ出力します。
<?php
// 例:自作スクリプトをフッターで読み込む
wp_enqueue_script(
'site-main',
get_template_directory_uri() . '/assets/js/main.js',
array('jquery'),
'1.0.0',
true // <= フッターへ
);
既に登録済みのスクリプトをフッターに移したい場合は、再登録で出力位置を変えます。依存関係に注意しつつ、ヘッダー登録を一度解除してからフッターで登録し直します。
<?php
add_action('wp_enqueue_scripts', function () {
// 例:jQuery をフッターに移す(依存多数のため検証必須)
if (wp_script_is('jquery', 'registered')) {
wp_deregister_script('jquery');
wp_register_script('jquery', includes_url('/js/jquery/jquery.min.js'), array(), null, true);
wp_enqueue_script('jquery');
}
}, 20);
次に「defer / async」を付与して解析停止を減らす
defer
は HTML の解析を止めずに取得し、DOM 構築完了後に登録順で実行します。async
は取得完了しだい即実行され順序保障がありません。依存関係があるライブラリは defer
、独立した計測タグなどは async
が安全です。WordPress 6.3 以降はスクリプトの「戦略」を付与できます。
<?php
// WP 6.3+:enqueue 時に strategy を指定
add_action('wp_enqueue_scripts', function () {
wp_enqueue_script('site-main', get_template_directory_uri() . '/assets/js/main.js', array(), '1.0', true);
wp_script_add_data('site-main', 'strategy', 'defer'); // または 'async'
});
旧バージョンでは script_loader_tag
フィルターで属性を付与します。
<?php
add_filter('script_loader_tag', function ($tag, $handle, $src) {
$defer_targets = array('site-main', 'another-lib'); // 順序維持したいもの
$async_targets = array('ga-tag'); // 独立しているもの
if (in_array($handle, $defer_targets, true)) {
return '<script src="' . esc_url($src) . '" defer></script>';
}
if (in_array($handle, $async_targets, true)) {
return '<script src="' . esc_url($src) . '" async></script>';
}
return $tag;
}, 10, 3);
不要スクリプトは読み込まないのが最良の最適化
使用していないプラグインやページに無関係なスクリプトは、読み込まないのが最速です。対象ハンドルを特定して条件付きでキューから外します。管理画面やログインページで外しすぎないようにフロントのみで実行します。
<?php
add_action('wp_enqueue_scripts', function () {
// 例:トップページ以外では slick を外す
if (!is_front_page()) {
wp_dequeue_script('slick-js');
wp_dequeue_style('slick-css');
}
}, 100);
WooCommerce など大規模プラグインは、カートやチェックアウト以外での読み込みを抑えるだけでも描画が軽くなります。動作要件に影響しない範囲で慎重に実施します。
DOM 依存コードは「DOMContentLoaded」で安全に
スクリプトをフッターへ移したり defer
を付けると、$(document).ready()
前提のコードが早すぎたり遅すぎたりする誤動作が出ることがあります。現代的には DOMContentLoaded
を明示して、DOM 構築後に初期化するのが安全です。
document.addEventListener('DOMContentLoaded', function () {
// DOM が構築されたら初期化
initSite();
});
インラインスクリプトの依存を解消する
ライブラリより前にインラインコードが出力されると、Uncaught ReferenceError
で止まり描画も遅れます。WordPress の wp_add_inline_script
を使うと、指定ハンドルの直後にインラインを出力でき、順序問題を解消できます。
<?php
wp_enqueue_script('site-main', get_template_directory_uri() . '/assets/js/main.js', array('jquery'), '1.0', true);
wp_add_inline_script('site-main', 'window.AppConfig = { lang: "ja" };', 'before');
// 'before' で main.js の直前、'after' で直後に出力
計測タグや外部 SDK は「遅延」か「同意後」に読み込む
広告タグ、A/B テスト、SNS SDK はレンダリングを止めやすく、CLS の悪化も招きます。async
を基本に、UI に関係ないものはユーザー操作後または同意取得後に load
イベントで遅延読み込みします。重要でないものは初回描画後まで待たせるだけで LCP が安定します。
window.addEventListener('load', function () {
var s = document.createElement('script');
s.src = 'https://example.com/analytics.js';
s.async = true;
document.head.appendChild(s);
});
ブロッキング調査の進め方とロールバックの保険
変更前に現状の読み込み順を把握し、影響の少ないものから段階的に移動・削減します。Chrome DevTools の Coverage で未使用コードを確認し、Performance でローディングタイムラインを観測しながら差分を評価します。テーマ更新やプラグイン更新に備えて、functions.php
の最適化はバージョン管理に入れ、事故時は即座に元へ戻せるようにします。
最小構成の実用テンプレート
フッターへ移動、主要スクリプトに defer
、計測タグは async
、ページ別の読み込み抑制を一括で行う最小実装例です。
<?php
add_action('wp_enqueue_scripts', function () {
// メイン
wp_enqueue_script('site-main', get_template_directory_uri() . '/assets/js/main.js', array(), '1.2.0', true);
if (function_exists('wp_script_add_data')) {
wp_script_add_data('site-main', 'strategy', 'defer');
}
// トップだけで必要なヒーロー用スクリプト
if (is_front_page()) {
wp_enqueue_script('hero', get_template_directory_uri() . '/assets/js/hero.js', array(), '1.0.0', true);
if (function_exists('wp_script_add_data')) {
wp_script_add_data('hero', 'strategy', 'defer');
}
}
}, 20);
// 旧 WP 向け:指定ハンドルに defer/async 属性を付与
add_filter('script_loader_tag', function ($tag, $handle, $src) {
if (in_array($handle, array('site-main', 'hero'), true)) {
return '<script src="' . esc_url($src) . '" defer></script>';
}
if ($handle === 'analytics') {
return '<script src="' . esc_url($src) . '" async></script>';
}
return $tag;
}, 10, 3);
// 不要スクリプトの抑制例
add_action('wp_enqueue_scripts', function () {
if (!is_front_page()) {
wp_dequeue_script('slick-js');
wp_dequeue_style('slick-css');
}
}, 100);
まとめ
体感速度の改善は、レンダリングを止める要因を順に減らすだけで着実に達成できます。第一にスクリプトをフッターへ移動し、第二に依存を壊さない範囲で defer
と async
を使い分け、第三にページ単位で不要な読み込みを止めます。インラインの順序と初期化タイミングを整え、計測系は後回しにする方針を徹底すれば、WordPress でも安定して LCP と CLS を引き下げられます。