サイトの読み込み速度や管理のしやすさを高めるには、必要なページだけにCSSやJSを読み込むのが効果的です。WordPressではwp_enqueue_scriptsやadmin_enqueue_scriptsのフックと条件分岐タグを組み合わせると、テーマに条件付きでアセットを読み込む実装が簡潔に書けます。ここでは、フロント用・管理画面用・ログイン画面用の基本から、子テーマでのパス指定、依存関係、バージョニング、defer付与、不要アセットの解除まで、実運用で役立つパターンをまとめます。
基本:wp_enqueue_scriptsで条件分岐して読み込む
テーマのfunctions.phpに記述し、is_front_pageやis_page、is_singularなどの条件分岐タグで読み込む範囲を絞ります。ファイルの更新時刻をバージョンに使うと、ファイルを書き換えたときにキャッシュが自動で更新されます。依存配列を指定すれば読み込み順も安全に制御できます。
スクリプトの登録の基本はwp_enqueue_scriptの使い方、スタイルシートはwp_enqueue_styleの使い方で詳しく解説しています。
<?php
add_action('wp_enqueue_scripts', function () {
$dir = get_stylesheet_directory();
$uri = get_stylesheet_directory_uri();
// 共通CSS(全ページ)
$common_css = $dir . '/assets/css/common.css';
if (file_exists($common_css)) {
wp_enqueue_style(
'theme-common',
$uri . '/assets/css/common.css',
[],
filemtime($common_css),
'all'
);
}
// トップページ限定のヒーロー用CSS
$hero_css = $dir . '/assets/css/hero.css';
if (is_front_page() && file_exists($hero_css)) {
wp_enqueue_style(
'theme-hero',
$uri . '/assets/css/hero.css',
['theme-common'],
filemtime($hero_css),
'all'
);
}
// 記事詳細のみJSを読み込む(jQueryに依存)
$article_js = $dir . '/assets/js/article.js';
if (is_singular('post') && file_exists($article_js)) {
wp_enqueue_script(
'theme-article',
$uri . '/assets/js/article.js',
['jquery'],
filemtime($article_js),
true
);
}
// 固定ページ「/contact/」だけフォーム用JS
$form_js = $dir . '/assets/js/form.js';
if (is_page('contact') && file_exists($form_js)) {
wp_enqueue_script(
'theme-form',
$uri . '/assets/js/form.js',
[],
filemtime($form_js),
true
);
}
});
本サイトのように子テーマ(cocoon-child-master)でカスタマイズする場合、get_template_directory()は親テーマのフォルダを返します。子テーマに置いたassets/css/common.cssなどを指定すると親テーマ側にはファイルがないため、読み込まれず表示も崩れます。file_existsで判定していると、エラーも出ないので原因に気づきにくくなります。子テーマのファイルは
get_stylesheet_directory()とget_stylesheet_directory_uri()で指定してください。子テーマ全体の構成は子テーマでfunctions.phpを正しく拡張する方法も参考になります。file_existsで存在を確認してからfilemtimeを呼んでいるのは、ファイルの書き忘れや削除があったときにPHPの警告を出さないためです。
投稿タイプやタクソノミーで条件分岐する
カスタム投稿タイプやアーカイブ画面は、URLの形ではなく機能で出し分けると保守が楽になります。
<?php
add_action('wp_enqueue_scripts', function () {
$dir = get_stylesheet_directory();
$uri = get_stylesheet_directory_uri();
// カスタム投稿タイプ product の詳細ページ専用
$pjs = $dir . '/assets/js/product-single.js';
if (is_singular('product') && file_exists($pjs)) {
wp_enqueue_script(
'product-single',
$uri . '/assets/js/product-single.js',
[],
filemtime($pjs),
true
);
}
// product のアーカイブ・タクソノミー一覧
$plist = $dir . '/assets/css/product-list.css';
if ((is_post_type_archive('product') || is_tax('brand')) && file_exists($plist)) {
wp_enqueue_style(
'product-list',
$uri . '/assets/css/product-list.css',
['theme-common'],
filemtime($plist)
);
}
});
ブロックの存在に応じて読み込む
同じテンプレートでも、本文に特定のブロックが含まれるときだけ資産を読み込むと無駄が減ります。has_blockは第2引数に投稿IDを渡せるため、管理画面でも判定はできます。ただし、この処理はwp_enqueue_scriptsの中でフロントの表示時に実行されるため、フロントの判定に使うのが基本です。
注意点として、has_blockは投稿本文の中身を見るだけです。再利用ブロック(core/block)として挿入された中のブロックは検出できないので、その場合は読み込み漏れが起きないよう、テンプレート側で指定するなどの対策をしてください。
<?php
add_action('wp_enqueue_scripts', function () {
$dir = get_stylesheet_directory();
$uri = get_stylesheet_directory_uri();
$gcss = $dir . '/assets/css/gallery.css';
$gjs = $dir . '/assets/js/gallery.js';
// 投稿に core/gallery ブロックが含まれる場合だけ読み込む
if (is_singular() && has_block('core/gallery', get_the_ID())) {
if (file_exists($gcss)) {
wp_enqueue_style('theme-gallery', $uri . '/assets/css/gallery.css', [], filemtime($gcss));
}
if (file_exists($gjs)) {
wp_enqueue_script('theme-gallery', $uri . '/assets/js/gallery.js', [], filemtime($gjs), true);
}
}
});
スクリプトにdeferを付与する
読み込みブロッキングを避けたい場合は、defer属性を付与します。WordPress 6.3以降であれば、ハンドル名を指定してwp_script_add_data()のstrategyにdeferを渡すのが公式な書き方です。
<?php
// WordPress 6.3以降:ハンドル名を指定して defer を付与する
wp_script_add_data('theme-article', 'strategy', 'defer');
wp_script_add_data('theme-form', 'strategy', 'defer');
wp_script_add_data('product-single', 'strategy', 'defer');
6.3より前のバージョンでは、script_loader_tagフィルターで書き換える方法もあります。ただしこのフィルターは、出力されるすべてのscriptタグを通ります。インラインscriptに属性を付けても効果はないものの、意図しないタグを書き換えないよう、対象のハンドルを確実に絞り込んでください。
deferを付けるのは、DOMの構築後に動けば十分なスクリプトだけにしてください。他のスクリプトより先に実行されている前提で書かれたものには付けないようにします。
不要なプラグインのCSS/JSを特定ページで解除する
プラグインが全ページでアセットを出力する場合、対象外のページでだけ解除すると軽量化できます。wp_print_stylesとwp_print_scriptsのアクションは、キューの出力前に発火するため、priority 100で解除すれば有効です。解除するハンドル名は、プラグインが出力するソースで確認してから指定してください。
<?php
// 問い合わせフォーム以外のページでは Contact Form 7 のCSS/JSを外す
add_action('wp_print_styles', function () {
if (!is_page('contact')) {
wp_dequeue_style('contact-form-7');
wp_deregister_style('contact-form-7');
}
}, 100);
add_action('wp_print_scripts', function () {
if (!is_page('contact')) {
wp_dequeue_script('contact-form-7');
wp_deregister_script('contact-form-7');
}
}, 100);
管理画面とログイン画面での条件付き読み込み
投稿や固定ページの編集画面だけ、あるいは特定の設定ページだけに管理用アセットを読み込むと、管理画面の体感速度が上がります。管理画面の独自メニューの作り方は管理画面に独自メニューを追加する方法をご覧ください。ログイン画面は、wp_enqueue_scriptsではなく専用のフックを使います。
<?php
// 管理画面
add_action('admin_enqueue_scripts', function ($hook) {
$dir = get_stylesheet_directory();
$uri = get_stylesheet_directory_uri();
// 投稿の作成・編集画面だけ
$admin_css = $dir . '/assets/admin/editor-help.css';
if (in_array($hook, ['post.php', 'post-new.php'], true) && file_exists($admin_css)) {
wp_enqueue_style(
'editor-help',
$uri . '/assets/admin/editor-help.css',
[],
filemtime($admin_css)
);
}
// 独自の設定ページだけ(例:add_menu_page で slug を theme-settings にした場合)
$admin_js = $dir . '/assets/admin/settings.js';
if ($hook === 'toplevel_page_theme-settings' && file_exists($admin_js)) {
wp_enqueue_script(
'theme-settings',
$uri . '/assets/admin/settings.js',
['jquery'],
filemtime($admin_js),
true
);
}
});
// ログイン画面
add_action('login_enqueue_scripts', function () {
$dir = get_stylesheet_directory();
$login_css = $dir . '/assets/css/login.css';
if (file_exists($login_css)) {
wp_enqueue_style(
'login-style',
get_stylesheet_directory_uri() . '/assets/css/login.css',
[],
filemtime($login_css)
);
}
});
wp_register_*で登録してから必要な時だけenqueueする
大きなライブラリは常時読み込まず、登録だけ行い、条件を満たしたときにenqueueすると管理しやすくなります。CDNから読み込む場合はバージョンを明示しておくと、キャッシュの扱いが分かりやすくなります。
<?php
add_action('wp_enqueue_scripts', function () {
$dir = get_stylesheet_directory();
$uri = get_stylesheet_directory_uri();
// 常時は読み込まず、登録だけしておく
wp_register_script(
'swiper',
'https://cdn.jsdelivr.net/npm/swiper@10/swiper-bundle.min.js',
[],
'10.0.0',
true
);
wp_register_style(
'swiper',
'https://cdn.jsdelivr.net/npm/swiper@10/swiper-bundle.min.css',
[],
'10.0.0'
);
// スライダーを置いた固定ページだけ読み込む
$slider_js = $dir . '/assets/js/slider-init.js';
if (is_page_template('templates/page-slider.php') && file_exists($slider_js)) {
wp_enqueue_style('swiper');
wp_enqueue_script('swiper');
wp_enqueue_script(
'slider-init',
$uri . '/assets/js/slider-init.js',
['swiper'],
filemtime($slider_js),
true
);
}
});
実運用のチェックポイントとトラブル回避
- is_*タグは、メインクエリが確定したあとに判定されます。wp_enqueue_scriptsの中で使うのが基本です。
- 依存関係が崩れる原因は、ほとんどがハンドル名の誤りです。親にあたるハンドルを依存配列に正しく指定してください。
- 子テーマではget_stylesheet_directory()系、親テーマのファイルだけをget_template_directory()系で指定します。
- filemtimeでバージョンを付けていれば、ファイルを更新するたびにバージョンが変わるため、ブラウザは新しいファイルを取得します。CDNを使う場合は、キャッシュの扱いに合わせてファイル名にハッシュを付ける方式も検討してください。
- プラグインのアセットを解除するときは、高い優先度でフックし、実際に出力されているかを確認してから本番に反映してください。
よくある質問(FAQ)
まとめ
WordPressの条件分岐タグとenqueue周りのフックを組み合わせれば、テーマに必要なCSSやJSだけを読み込む設計ができます。子テーマではパスの指定を正しく行い、file_existsで安全にバージョンを付け、deferや不要アセットの解除まで一連のルールとして整えると、表示速度と保守性を両立できます。スタイルシートの基本はwp_enqueue_styleの使い方、functions.phpを整理する方法はfunctions.phpを分割して管理する方法も合わせて確認してください。

