WordPress独自テーマでCSSやJSのバージョン番号をWP管理画面で管理する仕組み

設定ファイルの初期値と管理画面変更を両立する実装例

WordPressの独自テーマを運用していると、CSSやJavaScriptを更新したのに、ブラウザキャッシュの影響で変更が反映されないことがあります。
このときによく使われるのが、アセットURLに付与するバージョン番号です。

たとえば、以下のような形です。

/style.css?ver=1.0.0
/main.js?ver=1.0.0

この ver の値を変更することで、ブラウザに「別バージョンのファイル」と認識させやすくなり、更新内容を反映しやすくできます。

本記事では、WordPress独自テーマにおいて、CSSやJSなどのアセットバージョンを設定ファイルで初期管理しつつ、管理画面からも変更できる仕組みを、実装例付きで詳しく解説します。


なぜアセットのバージョン管理が必要なのか

CSSやJSは、ブラウザにキャッシュされやすいファイルです。
そのため、テーマ側でファイルを更新しても、ユーザー環境では古いまま表示されることがあります。

特に次のようなケースでは、バージョン管理の仕組みが役立ちます。

  • デザイン修正後に、確実に新しいCSSを読み込ませたい
  • JavaScriptのバグ修正をすぐ反映したい
  • CDNやサーバーキャッシュの影響を受けやすい
  • 運用担当者がコードを触らずに更新できるようにしたい

単に functions.php に固定値を書く方法でも対応はできますが、運用を考えると、設定ファイルの初期値管理画面からの上書きを両立するほうが扱いやすくなります。


今回の実装方針

今回紹介する仕組みは、次の構成です。

  1. 設定ファイルにデフォルトのバージョン番号を定義する
  2. 管理画面に設定項目を作る
  3. 管理画面に保存された値があればそれを優先する
  4. 値が未設定なら設定ファイルの値を使う
  5. CSSやJSの読み込み時は共通関数からバージョン番号を取得する

この設計にすると、次のようなメリットがあります。

  • コード上に標準設定を残せる
  • 初期構築時の状態が明確になる
  • 緊急時に管理画面からすぐ変更できる
  • アセット管理のルールを統一しやすい

想定するディレクトリ構成

今回は、独自テーマ内に以下のような構成を用意する想定で進めます。

your-theme/
├── assets/
│   ├── css/
│   │   └── common.css
│   └── js/
│       └── main.js
├── config/
│   └── asset-settings.php
├── inc/
│   ├── asset-functions.php
│   └── admin-asset-settings.php
├── functions.php
└── style.css

役割は以下のとおりです。

  • config/asset-settings.php
    デフォルト設定を定義する
  • inc/asset-functions.php
    設定取得・バージョン取得・enqueue処理をまとめる
  • inc/admin-asset-settings.php
    管理画面の設定ページを実装する
  • functions.php
    各ファイルの読み込みを行う

1. 設定ファイルにデフォルト値を定義する

まず、テーマのデフォルト設定ファイルを作成します。

config/asset-settings.php

<?php

return array(
    'asset_version' => '1.0.0',
);

このファイルは、テーマの初期状態を定義するものです。
管理画面で何も設定されていない場合は、この値が使われます。

この方式の利点

  • Gitで標準値を管理できる
  • 初回構築時の挙動が明確になる
  • 開発メンバー間で認識を揃えやすい

2. バージョン取得用の共通関数を作る

次に、設定ファイルと管理画面の値をまとめて扱うための関数を作成します。

inc/asset-functions.php

<?php

if (!defined('ABSPATH')) {
    exit;
}

/**
 * テーマのアセット設定ファイルを読み込む
 *
 * 設定ファイルが存在しない場合でもエラーにせず、
 * 空配列を返して安全に処理を継続する。
 *
 * @return array
 */
function mytheme_get_asset_config()
{
    $config_file = get_template_directory() . '/config/asset-settings.php';

    if (!file_exists($config_file)) {
        return array();
    }

    $config = require $config_file;

    return is_array($config) ? $config : array();
}

/**
 * アセットのデフォルトバージョン番号を取得する
 *
 * 設定ファイルに asset_version が存在すればその値を返し、
 * なければ最終フォールバックとして 1.0.0 を返す。
 *
 * @return string
 */
function mytheme_get_default_asset_version()
{
    $config = mytheme_get_asset_config();

    if (!empty($config['asset_version'])) {
        return (string) $config['asset_version'];
    }

    return '1.0.0';
}

/**
 * 管理画面で保存されたアセットバージョン番号を取得する
 *
 * WordPress の options テーブルから値を取得する。
 * 値が未設定または空文字の場合は空文字を返す。
 *
 * @return string
 */
function mytheme_get_saved_asset_version()
{
    $value = get_option('mytheme_asset_version', '');

    return is_string($value) ? trim($value) : '';
}

/**
 * 実際に使用するアセットバージョン番号を取得する
 *
 * 優先順位:
 * 1. 管理画面で保存された値
 * 2. 設定ファイルのデフォルト値
 * 3. 最終フォールバック値
 *
 * @return string
 */
function mytheme_get_asset_version()
{
    $saved_version = mytheme_get_saved_asset_version();

    if ($saved_version !== '') {
        return $saved_version;
    }

    return mytheme_get_default_asset_version();
}

/**
 * CSS / JS のバージョンとして使う値をサニタイズする
 *
 * URLパラメータとして扱うため、英数字・ドット・ハイフン・アンダースコアのみ許可する。
 * 不正な文字が含まれる場合は除去する。
 *
 * @param string $value
 * @return string
 */
function mytheme_sanitize_asset_version($value)
{
    $value = (string) $value;
    $value = trim($value);
    $value = preg_replace('/[^A-Za-z0-9._-]/', '', $value);

    return $value;
}

/**
 * テーマの CSS / JS を読み込む
 *
 * すべてのアセットで共通バージョンを使う例。
 * 必要に応じて個別ハンドルや依存関係を追加する。
 *
 * @return void
 */
function mytheme_enqueue_assets()
{
    $asset_version = mytheme_sanitize_asset_version(mytheme_get_asset_version());

    if ($asset_version === '') {
        $asset_version = '1.0.0';
    }

    wp_enqueue_style(
        'mytheme-common',
        get_template_directory_uri() . '/assets/css/common.css',
        array(),
        $asset_version
    );

    wp_enqueue_script(
        'mytheme-main',
        get_template_directory_uri() . '/assets/js/main.js',
        array(),
        $asset_version,
        true
    );
}
add_action('wp_enqueue_scripts', 'mytheme_enqueue_assets');

3. 管理画面の設定ページを作る

続いて、管理画面からアセットバージョンを変更できるようにします。

今回は、WordPressの「設定」メニュー配下に専用ページを追加する例です。

inc/admin-asset-settings.php

<?php

if (!defined('ABSPATH')) {
    exit;
}

/**
 * 管理画面メニューに設定ページを追加する
 *
 * 「設定 > アセットバージョン設定」として表示する。
 *
 * @return void
 */
function mytheme_add_asset_settings_page()
{
    add_options_page(
        'アセットバージョン設定',
        'アセットバージョン設定',
        'manage_options',
        'mytheme-asset-settings',
        'mytheme_render_asset_settings_page'
    );
}
add_action('admin_menu', 'mytheme_add_asset_settings_page');

/**
 * 設定項目を登録する
 *
 * register_setting により options テーブルへ保存可能にする。
 * sanitize_callback で入力値を制御する。
 *
 * @return void
 */
function mytheme_register_asset_settings()
{
    register_setting(
        'mytheme_asset_settings_group',
        'mytheme_asset_version',
        array(
            'type'              => 'string',
            'sanitize_callback' => 'mytheme_sanitize_asset_version',
            'default'           => '',
        )
    );
}
add_action('admin_init', 'mytheme_register_asset_settings');

/**
 * 設定ページを描画する
 *
 * 現在の保存値と設定ファイル上のデフォルト値を表示し、
 * 運用者が状況を把握しやすいようにする。
 *
 * @return void
 */
function mytheme_render_asset_settings_page()
{
    if (!current_user_can('manage_options')) {
        return;
    }

    $saved_version   = mytheme_get_saved_asset_version();
    $default_version = mytheme_get_default_asset_version();
    $current_version = mytheme_get_asset_version();
    ?>
    <div class="wrap">
        <h1>アセットバージョン設定</h1>

        <p>テーマで読み込む CSS / JS のバージョン番号を設定します。</p>
        <p>管理画面の値が入力されている場合はその値を優先し、未入力の場合は設定ファイルのデフォルト値を使用します。</p>

        <table class="widefat striped" style="max-width: 840px; margin: 20px 0;">
            <tbody>
                <tr>
                    <th style="width: 240px;">現在適用される値</th>
                    <td><code><?php echo esc_html($current_version); ?></code></td>
                </tr>
                <tr>
                    <th>管理画面の保存値</th>
                    <td>
                        <?php if ($saved_version !== '') : ?>
                            <code><?php echo esc_html($saved_version); ?></code>
                        <?php else : ?>
                            <span>未設定</span>
                        <?php endif; ?>
                    </td>
                </tr>
                <tr>
                    <th>設定ファイルのデフォルト値</th>
                    <td><code><?php echo esc_html($default_version); ?></code></td>
                </tr>
            </tbody>
        </table>

        <form method="post" action="options.php">
            <?php settings_fields('mytheme_asset_settings_group'); ?>

            <table class="form-table" role="presentation">
                <tbody>
                    <tr>
                        <th scope="row">
                            <label for="mytheme_asset_version">アセットバージョン番号</label>
                        </th>
                        <td>
                            <input
                                type="text"
                                id="mytheme_asset_version"
                                name="mytheme_asset_version"
                                value="<?php echo esc_attr($saved_version); ?>"
                                class="regular-text"
                            />
                            <p class="description">
                                例: <code>1.0.1</code> / <code>20260405</code> / <code>20260405-01</code><br>
                                空欄で保存すると、設定ファイルのデフォルト値を使用します。
                            </p>
                        </td>
                    </tr>
                </tbody>
            </table>

            <?php submit_button('保存する'); ?>
        </form>
    </div>
    <?php
}

4. functions.php で読み込む

作成したファイルを functions.php から読み込みます。

functions.php

<?php

if (!defined('ABSPATH')) {
    exit;
}

require_once get_template_directory() . '/inc/asset-functions.php';
require_once get_template_directory() . '/inc/admin-asset-settings.php';

これで、フロント側のCSS/JS読み込みと、管理画面側の設定ページの両方が有効になります。


実際の動作イメージ

この仕組みでは、次のような優先順位で値が決まります。

初期状態

設定ファイル:

return array(
    'asset_version' => '1.0.0',
);

管理画面の保存値: 未設定

この場合、読み込まれるURLは以下のようになります。

/assets/css/common.css?ver=1.0.0
/assets/js/main.js?ver=1.0.0

管理画面で 1.0.1 を保存した場合

管理画面の保存値: 1.0.1

この場合、設定ファイルより管理画面の値が優先されます。

/assets/css/common.css?ver=1.0.1
/assets/js/main.js?ver=1.0.1

管理画面を空欄で保存した場合

管理画面の保存値: 空

この場合、再び設定ファイルのデフォルト値に戻ります。

/assets/css/common.css?ver=1.0.0
/assets/js/main.js?ver=1.0.0

この実装のポイント

1. 設定ファイルに初期状態を持たせている

設定ファイルにデフォルト値を持たせることで、テーマとしての標準状態が明確になります。
Git管理しやすく、環境ごとの差異も把握しやすくなります。

2. 管理画面から上書きできる

本番反映後にキャッシュが残った場合でも、コードを修正せずに管理画面からすぐ変更できます。
エンジニア以外の担当者でも扱いやすいのが利点です。

3. 取得処理を共通化している

各所で get_option() や設定ファイル読み込みを直接書かず、必ず mytheme_get_asset_version() を通すことで、管理ロジックが散らばりません。

4. サニタイズを入れている

URLパラメータに入る値なので、最低限の文字制限をかけています。
このような防御を入れておくと、想定外の入力によるトラブルを防ぎやすくなります。


より実務向けに拡張する場合

ここまでの構成でも十分実用的ですが、実案件では次のような拡張も考えられます。


CSS用とJS用で分けて管理する

共通バージョン1つでも問題ありませんが、CSSだけ変更した場合にJSのキャッシュまで無効化したくないことがあります。
その場合は、設定を分けて持つ方法が有効です。

たとえば、設定ファイルを以下のようにします。

<?php

return array(
    'asset_version'     => '1.0.0',
    'css_version'       => '1.0.0',
    'js_version'        => '1.0.0',
);

そして、管理画面にも以下のような項目を追加します。

  • 共通バージョン
  • CSSバージョン
  • JSバージョン

運用ルールとしては、以下のようにすると分かりやすいです。

  • 個別値があれば個別値を優先
  • 個別値が空なら共通バージョンを使う
  • 共通バージョンも空なら設定ファイルの初期値を使う

本番公開時だけ変更する運用にする

アセットバージョンは、頻繁に変更しすぎるとキャッシュのメリットが減ります。
そのため、以下のようなルールを決めておくと運用しやすくなります。

  • 軽微な開発中は変更しない
  • 本番反映時のみ更新する
  • 緊急修正時だけ日付形式にする

例:

  • 通常: 1.0.0
  • 次回反映: 1.0.1
  • 緊急対応: 20260405-01

更新履歴を残す

複数人で運用している場合は、誰がいつ変更したかが分かると便利です。
簡易的には、保存時に以下を別オプションに残す方法があります。

  • 更新日時
  • 更新ユーザーID
  • 変更前の値

そこまで必要ない案件も多いですが、長期運用サイトでは有効です。


filemtime() と併用する考え方

案件によっては、管理画面による手動更新ではなく、自動で更新日時を使いたいこともあります。
ただし、今回のように「管理画面で変えたい」という要件が明確な場合は、まず手動管理のほうが分かりやすいです。

どうしても自動更新も併用したい場合は、以下のような優先順位も考えられます。

  1. 管理画面で保存された値
  2. filemtime による自動値
  3. 設定ファイルのデフォルト値

ただしこの構成は少し複雑になるため、最初から入れすぎないほうが保守しやすいです。


実装時の注意点

オプション名はテーマ固有にする

今回の例では mytheme_asset_version という名前を使っています。
実案件では、テーマ名やプレフィックスに合わせて重複しにくい名前にしてください。

子テーマ利用時は必要に応じて読み替える

今回のコードでは get_template_directory() を使っています。
親テーマ基準で問題ないならそのままでよいですが、子テーマ運用を前提とする場合は get_stylesheet_directory() を使う設計も検討できます。

キャッシュプラグインやCDNの仕様も確認する

URLのクエリパラメータ変更で反映されることが多いですが、利用中のキャッシュプラグインやCDNによっては挙動差があります。
そのため、実装後は本番相当環境で必ず確認したほうが安全です。

管理画面の入力ルールは事前に決める

運用担当者が複数いる場合は、以下を軽く共有しておくと混乱を防げます。

  • どのタイミングで変更するか
  • どの書式で入力するか
  • 変更後に何を確認するか

まとめ

WordPress独自テーマでCSSやJSなどのアセットバージョンを管理するなら、設定ファイルのデフォルト値管理画面からの上書き機能を組み合わせる構成が扱いやすいです。

今回の実装では、以下を実現しました。

  • 設定ファイルで初期値を定義
  • 管理画面で任意のバージョン番号を保存
  • 保存値があればそちらを優先
  • 未設定なら設定ファイルの値を使用
  • enqueue処理は共通関数を通して統一

この方式なら、開発時の見通しと運用時の柔軟性を両立しやすくなります。
特に、独自テーマを長く保守していく案件では、単純な固定値管理よりも実務向きの設計です。

最初は共通バージョン1つから始めて、必要に応じてCSS用・JS用に分ける形に拡張していくのが現実的でしょう。

コメント

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