Agent Skills by ALSEL
汎用ソフトウェア開発⭐ リポ 3品質スコア 76/100

wp-performance-review

WordPressのパフォーマンスコードレビューと最適化分析を実施します。WordPressのPHPコードのパフォーマンス問題のレビュー、テーマ・プラグインのスケーラビリティ監査、WP_Queryの最適化、キャッシング戦略の分析、本番運用前のコード確認、アンチパターンの検出に対応します。ユーザーが「パフォーマンスレビュー」「最適化監査」「WordPressが遅い」「クエリが遅い」「高トラフィック」「WordPressのスケーリング」「コードレビュー」「タイムアウト」「500エラー」「メモリ不足」「サイトが読み込めない」といった内容を提示した場合にも適用されます。データベースクエリ、フック、オブジェクトキャッシュ、AJAX、テンプレート読み込み、エディタ側のパフォーマンスにおけるアンチパターンを検出します。

description の原文を見る

WordPress performance code review and optimization analysis. Use when reviewing WordPress PHP code for performance issues, auditing themes/plugins for scalability, optimizing WP_Query, analyzing caching strategies, checking code before launch, or detecting anti-patterns, or when user mentions "performance review", "optimization audit", "slow WordPress", "slow queries", "high-traffic", "scale WordPress", "code review", "timeout", "500 error", "out of memory", or "site won't load". Detects anti-patterns in database queries, hooks, object caching, AJAX, template loading, and editor-side performance.

SKILL.md 本文

WordPress Performance Review スキル

概要

WordPress テーマ、プラグイン、カスタムコードの体系的なパフォーマンスコードレビュー。コアプリンシパル: 重大な問題(OOM、制限なしのクエリ、キャッシュ回避)を最初にスキャンし、その後警告、最後に最適化をレポートします。行番号と重要度レベルと共に報告してください。

使用場面

以下の場合に使用してください:

  • WordPress テーマまたはプラグインの PR/コードをレビューする
  • ユーザーがページロードの遅延、タイムアウト、または 500 エラーを報告している
  • 高トラフィックイベント(ローンチ、セール、バイラル)の前に監査する
  • WP_Query またはデータベース操作を最適化する
  • メモリ枯渇または DB ロックを調査する

以下の場合は使用しないでください:

  • セキュリティのみの監査(wp-security-review が利用可能な場合はそちらを使用)
  • Gutenberg ブロック開発パターン(wp-block-development が利用可能な場合はそちらを使用)
  • WordPress 特有でない一般的な PHP コードレビュー
  • WordPress パフォーマンス動作に関係しない製品または UX レビュー

コードレビューワークフロー

  1. ファイルタイプを特定し、以下の関連チェックを適用します
  2. 重大なパターンを最初にスキャン(OOM、制限なしのクエリ、キャッシュ回避)
  3. 警告をチェック(効率は悪いが致命的ではない)
  4. 最適化に注記(あると良い改善)
  5. 行番号付きでレポート、下記の出力形式を使用します

ファイルタイプ別チェック

プラグイン/テーマ PHP ファイル(functions.phpplugin.php*.php)

以下をスキャンしてください:

  • query_posts()重大: 使用禁止 - メインクエリを破損
  • posts_per_page.*-1 または numberposts.*-1重大: 制限なしのクエリ
  • session_start()重大: ページキャッシュを回避
  • add_action.*init.* または add_action.*wp_loaded → 高コスト処理が毎リクエスト実行されないか確認
  • update_option または add_option (非管理者コンテキスト) → 警告: ページロード時の DB 書き込み
  • wp_remote_get または wp_remote_post (キャッシュなし) → 警告: ブロッキング HTTP

WP_Query / データベースコード

以下をスキャンしてください:

  • posts_per_page 引数の欠落 → 警告: ブログ設定にデフォルト
  • 'meta_query''value' 比較使用 → 警告: インデックスなしの列スキャン
  • 大規模な post__not_in 配列(ページネーション/ソート付き) → 警告: 高コスト SQL を生成する可能性; ケースバイケースで確認
  • LIKE '%term%'(先頭のワイルドカード) → 警告: 全テーブルスキャン
  • no_found_rows => true の欠落(ページネーションなし) → 情報: 不要なカウント

AJAX ハンドラ(wp_ajax_*、REST エンドポイント)

以下をスキャンしてください:

  • admin-ajax.php の使用 → 情報: REST API を検討
  • POST メソッド(読み取り操作用) → 警告: キャッシュを回避
  • setInterval またはポーリングパターン → 重大: Self-DDoS リスク
  • nonce 検証の欠落 → セキュリティ問題(パフォーマンスではないが、フラグを立てる)

テンプレートファイル(テーマの *.php)

以下をスキャンしてください:

  • カスタムクエリ、キャッシュなしの get_post_meta()、またはループ内のリモート呼び出し → 警告: 繰り返し処理/N+1 リスク
  • ループ内のデータベースクエリ(N+1) → 重大: クエリ乗算
  • テンプレート内の wp_remote_get警告: レンダリングをブロック

JavaScript ファイル

以下をスキャンしてください:

  • 読み取り操作用の $.post(警告: キャッシュ可能性のため GET を使用
  • setInterval.*fetch\|ajax重大: ポーリングパターン
  • import _ from 'lodash'警告: フルライブラリインポートでバンドルを肥大化
  • ロード時に AJAX 呼び出しをする インライン <script> → 必要性を確認

ブロックエディタ/ Gutenberg ファイル(block.json、ブロック内の *.js)

以下をスキャンしてください:

  • エディタ側の重いデータ取得またはプレビュー ロジック → 警告: エディタロードを遅延
  • render コールバック内の wp_kses_post($content)警告: InnerBlocks を破損
  • 大規模なエディタバンドルまたは広範インポート → 警告: エディタランタイムを肥大化

アセット登録(functions.php*.php)

以下をスキャンしてください:

  • wp_enqueue_script (version なし) → 情報: キャッシュバスティング問題
  • wp_enqueue_script (defer/async 戦略なし) → 情報: レンダリングをブロック
  • THEME_VERSION 定数の欠落 → 情報: バージョン管理
  • wp_enqueue_script (条件チェックなし) → 警告: 特定ページのみ必要な場合、グローバルでロード

トランジェント & オプション

以下をスキャンしてください:

  • 動的キーを持つ set_transient(例: user_{$id}) → 警告: オブジェクトキャッシュなしのテーブル肥大化
  • 頻繁に変更されるデータの set_transient警告: キャッシング目的を無効化
  • トランジェント内の大規模データ(共有ホスティング) → 警告: オブジェクトキャッシュなしの DB 肥大化

WP-Cron

以下をスキャンしてください:

  • DISABLE_WP_CRON 定数の欠落 → 情報: Cron がページリクエスト時に実行
  • 長時間実行される Cron コールバック(全ユーザー/投稿をループ) → 重大: Cron キューをブロック
  • すでにスケジュール済みか確認なしの wp_schedule_event警告: 重複スケジュール

迅速な検出用検索パターン

# 重大な問題 - 最初にこれをスキャン
rg -n "posts_per_page\s*.*-1|numberposts\s*.*-1" .
rg -n "query_posts\s*\(" .
rg -n "session_start\s*\(" .
rg -n "setInterval.*(fetch|ajax|\\$\\.)" .

# フロントエンドでのデータベース書き込み
rg -n "update_option|add_option" . -g '*.php'

# キャッシュなしの高コスト関数
rg -n "url_to_postid|attachment_url_to_postid|count_user_posts" .

# キャッシュなしの外部 HTTP
rg -n "wp_remote_get|wp_remote_post|file_get_contents\s*\(\s*['\"]https?://" .

# キャッシュ回避リスク
rg -n "setcookie|session_start" .

# PHP コード アンチパターン
rg -n "in_array\s*\(" . -g '*.php'    # 厳密比較を手動確認
rg -n "<<<" .
rg -n "cache_results\s*=>\s*false|cache_results\s*,\s*false" .

# JavaScript バンドル問題
rg -n "import\s+_\s+from\s+['\"]lodash['\"]" . -g '*.{js,jsx,ts,tsx}'

# アセットロード問題
rg -n "wp_enqueue_script|wp_enqueue_style" . -g '*.php'

# トランジェント誤用
rg -n "set_transient\s*\([^,]+\\$" . -g '*.php'
rg -n "set_transient" . -g '*.php'    # 前の get_transient() チェックを手動確認

# WP-Cron 問題
rg -n "wp_schedule_event" . -g '*.php'  # wp_next_scheduled() ガードを手動確認

プラットフォームコンテキスト

異なるホスティング環境では異なるアプローチが必要です:

マネージド WordPress ホスト(WP Engine、Pantheon、Pressable、WordPress VIP など):

  • 多くの場合、オブジェクトキャッシュがすぐに利用可能
  • プラットフォーム固有のヘルパー関数がある場合があります(例: VIP の wpcom_vip_*)
  • ホストドキュメントで推奨パターンを確認してください

セルフホスト / 標準ホスティング:

  • 高コスト関数用のオブジェクトキャッシュラッパーを手動で実装
  • 永続的オブジェクトキャッシュ用の Redis または Memcached プラグインを検討
  • キャッシングレイヤー設定に対する責任が増加

共有ホスティング:

  • 制限なしのクエリと外部 HTTP について特に注意
  • リソースが限定されるため、パフォーマンス問題がより早く表面化
  • 永続的オブジェクトキャッシュがない場合があります

クイックリファレンス: 重大なアンチパターン

データベースクエリ

// ❌ CRITICAL: 制限なしのクエリ。
'posts_per_page' => -1

// ✅ GOOD: 合理的な制限を設定し、必要に応じてページネーション。
'posts_per_page' => 100,
'no_found_rows'  => true, // ページネーションなしの場合カウントをスキップ。

// ❌ CRITICAL: query_posts() を使用しないでください。
query_posts( 'cat=1' ); // ページネーション、条件を破損。

// ✅ GOOD: WP_Query または pre_get_posts フィルタを使用。
$query = new WP_Query( array( 'cat' => 1 ) );
// またはメインクエリを変更:
add_action( 'pre_get_posts', function( $query ) {
    if ( $query->is_main_query() && ! is_admin() ) {
        $query->set( 'cat', 1 );
    }
} );

// ❌ WARNING: 検証されていない ID はロジックバグを隠し、不要なクエリをトリガー。
$query = new WP_Query( array( 'p' => intval( $maybe_false_id ) ) );

// ✅ GOOD: クエリ前に ID を検証。
$post_id = absint( $maybe_false_id );
if ( $post_id > 0 ) {
    $query = new WP_Query( array( 'p' => $post_id ) );
}

// ❌ WARNING: 先頭ワイルドカード付き LIKE (全テーブルスキャン)。
$wpdb->get_results( "SELECT * FROM wp_posts WHERE post_title LIKE '%term%'" );

// ✅ GOOD: 末尾ワイルドカードのみを使用、または WP_Query の 's' パラメータを使用。
$wpdb->get_results( $wpdb->prepare(
    "SELECT * FROM wp_posts WHERE post_title LIKE %s",
    $wpdb->esc_like( $term ) . '%'
) );

// ❌ WARNING: 大規模な NOT IN クエリは高コストになる可能性、特にページネーション付き。
'post__not_in' => $excluded_ids

// ✅ GOOD: ポジティブインクルージョン、小規模除外リスト、または事前計算した候補 ID を優先。
'post__in' => $candidate_ids

フック & アクション

// ❌ WARNING: init を経由して毎リクエスト実行されるコード。
add_action( 'init', 'expensive_function' );

// ✅ GOOD: 高コスト処理を実行前にコンテキストをチェック。
add_action( 'init', function() {
    if ( is_admin() || wp_doing_cron() ) {
        return;
    }
    // フロントエンドのみのコードはここ。
} );

// ❌ CRITICAL: 毎ページロード時のデータベース書き込み。
add_action( 'wp_head', 'prefix_bad_tracking' );
function prefix_bad_tracking() {
    update_option( 'last_visit', time() );
}

// ✅ GOOD: オブジェクトキャッシュバッファを使用し、cron 経由でフラッシュ。
add_action( 'shutdown', function() {
    wp_cache_incr( 'page_views_buffer', 1, 'counters' );
} );

// ❌ WARNING: admin-ajax.php を使用してしまった。
// 優先: register_rest_route() - よりスリムなブートストラップ。

PHP コード

// ❌ WARNING: O(n) ルックアップ - 連想配列で isset() を使用。
in_array( $value, $array ); // また strict = true も欠落。

// ✅ GOOD: isset() での O(1) ルックアップ。
$allowed = array( 'foo' => true, 'bar' => true );
if ( isset( $allowed[ $value ] ) ) {
    // 処理。
}

// ❌ WARNING: Heredoc は後のエスケープを防止。
$html = <<<HTML
<div>$unescaped_content</div>
HTML;

// ✅ GOOD: 出力時にエスケープ。
printf( '<div>%s</div>', esc_html( $content ) );

キャッシング問題

// ❌ WARNING: キャッシュなしの高コスト関数呼び出し。
url_to_postid( $url );
attachment_url_to_postid( $attachment_url );
count_user_posts( $user_id );
wp_oembed_get( $url );

// ✅ GOOD: オブジェクトキャッシュでラップ(どのホストでも機能)。
function prefix_cached_url_to_postid( $url ) {
    $cache_key = 'url_to_postid_' . md5( $url );
    $post_id   = wp_cache_get( $cache_key, 'url_lookups' );

    if ( false === $post_id ) {
        $post_id = url_to_postid( $url );
        wp_cache_set( $cache_key, $post_id, 'url_lookups', HOUR_IN_SECONDS );
    }

    return $post_id;
}

// ✅ GOOD: WordPress VIP 上では代わりにプラットフォームヘルパーを使用。
// wpcom_vip_url_to_postid(), wpcom_vip_attachment_url_to_postid() など。

// ❌ WARNING: 大規模な自動ロードオプション。
add_option( 'prefix_large_data', $data ); // 追加: , '', 'no' for autoload。

// ❌ INFO: バッチルックアップ用の wp_cache_get_multiple が欠落。
foreach ( $ids as $id ) {
    wp_cache_get( "key_{$id}" );
}

AJAX & 外部リクエスト

// ❌ WARNING: AJAX POST リクエスト(キャッシュを回避)。
$.post( ajaxurl, data ); // 優先: 読み取り操作用の $.get()。

// ❌ CRITICAL: ポーリングパターン(Self-DDoS)。
setInterval( () => fetch( '/wp-json/...' ), 5000 );
// ❌ WARNING: ページロード時の同期外部 HTTP。
wp_remote_get( $url ); // 結果をキャッシュまたは cron に移動。

// ✅ GOOD: タイムアウトを設定しエラーを処理。
$response = wp_remote_get( $url, array( 'timeout' => 2 ) );
if ( is_wp_error( $response ) ) {
    return get_fallback_data();
}

WP Cron

// INFO: 高トラフィックまたは cron が多いサイトではリクエスト駆動の cron で十分でない場合があります。
// wp-config.php に追加を検討:
define( 'DISABLE_WP_CRON', true );
// サーバー cron 経由で実行: * * * * * wp cron event run --due-now

// ❌ CRITICAL: 長時間実行 cron が全キューをブロック。
add_action( 'my_daily_sync', function() {
    foreach ( get_users() as $user ) { // 50k ユーザー = 数時間。
        sync_user_data( $user );
    }
} );

// ✅ GOOD: 再スケジュールでのバッチ処理。
add_action( 'my_batch_sync', function() {
    $offset = (int) get_option( 'sync_offset', 0 );
    $users  = get_users( array( 'number' => 100, 'offset' => $offset ) );

    if ( empty( $users ) ) {
        delete_option( 'sync_offset' );
        return;
    }

    foreach ( $users as $user ) {
        sync_user_data( $user );
    }

    update_option( 'sync_offset', $offset + 100 );
    wp_schedule_single_event( time() + 60, 'my_batch_sync' );
} );

// ❌ WARNING: スケジュール済みか確認せずスケジュール。
wp_schedule_event( time(), 'hourly', 'my_task' ); // 重複を作成!

// ✅ GOOD: スケジュール前に確認。
if ( ! wp_next_scheduled( 'my_task' ) ) {
    wp_schedule_event( time(), 'hourly', 'my_task' );
}

キャッシュ回避問題

// ❌ CRITICAL: プラグインがフロントエンドで PHP セッションを開始(全ページキャッシュを回避)。
session_start(); // プラグインでこれを確認 - サイト全体がキャッシュ不可になります!

// ❌ WARNING: ユニークなクエリパラメータがキャッシュミスを作成。
// https://example.com/?utm_source=fb&utm_campaign=123&fbclid=abc
// ユニークな URL ごと = 個別キャッシュエントリ = キャッシュミス。
// ソリューション: CDN/エッジレベルでマーケティングパラメータをストリップ。

// ❌ WARNING: パブリックページでクッキーを設定。
setcookie( 'visitor_id', $id ); // そのユーザーのキャッシュを防止。

トランジェント誤用

// ❌ WARNING: 動的トランジェントキーがテーブル肥大化を作成(オブジェクトキャッシュなし)。
set_transient( "user_{$user_id}_cart", $data, HOUR_IN_SECONDS );
// 10,000 ユーザー = wp_options に 10,000 行!

// ✅ GOOD: ユーザー固有データ用にオブジェクトキャッシュを使用。
wp_cache_set( "cart_{$user_id}", $data, 'user_carts', HOUR_IN_SECONDS );

// ❌ WARNING: 頻繁に変更されるデータのトランジェント(目的を無効化)。
set_transient( 'visitor_count', $count, 60 ); // 毎分変更。

// ✅ GOOD: 不安定なデータ用にオブジェクトキャッシュを使用。
wp_cache_set( 'visitor_count', $count, 'stats' );

// ❌ WARNING: 共有ホスティングでのトランジェント内の大規模データ。
set_transient( 'api_response', $megabytes_of_json, DAY_IN_SECONDS );
// オブジェクトキャッシュなし = wp_options 内のシリアライズされた blob。

// ✅ GOOD: トランジェント使用前にホスティングをチェック。
if ( wp_using_ext_object_cache() ) {
    set_transient( 'api_response', $data, DAY_IN_SECONDS );
} else {
    // 共有ホスティングではファイル保存またはキャッシュをスキップ。
}

アセットロード

// ❌ WARNING: 特定ページのみ必要な場合、アセットがグローバルでロード。
add_action( 'wp_enqueue_scripts', function() {
    wp_enqueue_script( 'contact-form-js', ... );
    wp_enqueue_style( 'contact-form-css', ... );
} );

// ✅ GOOD: ページ/テンプレートベースの条件付きエンキュー。
add_action( 'wp_enqueue_scripts', function() {
    if ( is_page( 'contact' ) || is_page_template( 'contact-template.php' ) ) {
        wp_enqueue_script( 'contact-form-js', ... );
        wp_enqueue_style( 'contact-form-css', ... );
    }
} );

// ✅ GOOD: ショップページでのみ WooCommerce アセットをロード。
add_action( 'wp_enqueue_scripts', function() {
    if ( ! is_woocommerce() && ! is_cart() && ! is_checkout() ) {
        wp_dequeue_style( 'woocommerce-general' );
        wp_dequeue_script( 'wc-cart-fragments' );
    }
} );

外部 API リクエスト

// ❌ WARNING: タイムアウトが設定されていない(デフォルト 5 秒)。
wp_remote_get( $url ); // タイムアウト設定: array( 'timeout' => 2 )。

// ❌ WARNING: API 失敗のエラー処理がない。
$response = wp_remote_get( $url );
echo $response['body']; // 最初に is_wp_error() をチェック!

サイトマップ & リダイレクト

// ❌ WARNING: ディープアーカイブ用のサイトマップ生成(クローラーが大量にアクセス)。
// ソリューション: 古い投稿タイプを除外、生成済みサイトマップをキャッシュ。

// ❌ CRITICAL: CPU を消費するリダイレクトループ。
// デバッグ: x-redirect-by ヘッダー、wp_debug_backtrace_summary()。

投稿メタクエリ

// ❌ WARNING: インデックスなしの meta_value を検索。
'meta_query' => array(
    array(
        'key'   => 'color',
        'value' => 'red',
    ),
)
// より良い: タクソノミーを使用またはメタキー名に値をエンコード。

// ❌ WARNING: バイナリメタ値がバリュースキャンを必要。
'meta_key'   => 'featured',
'meta_value' => 'true',
// より良い: 'is_featured' キーの有無 = true/false。

パターン詳細なコンテキスト用: references/anti-patterns.md をロード

重要度定義

重要度説明
重大スケール時に障害を引き起こす(OOM、500 エラー、DB ロック)
警告負荷下でパフォーマンスを低下
情報最適化の機会

出力形式

以下のようにして成果をまとめてください:

## Performance Review: [ファイル名/コンポーネント]

### 重大な問題
- **Line X**: [問題] - [説明] - [修正]

### 警告  
- **Line X**: [問題] - [説明] - [修正]

### 推奨事項
- [最適化の機会]

### サマリー
- 合計問題数: X 重大、Y 警告、Z 情報
- 推定影響: [高/中/低]

一般的なミス

パフォーマンスレビューを実施する際、これらのエラーを避けてください:

ミスなぜ間違いか修正
管理者のみのコード内の posts_per_page => -1 をフラグする管理者クエリはパブリックスケールに直面しないコンテキストを確認 - 管理者、CLI、cron はより低リスク
プラグイン内の session_start() を見落とすキャッシュ回避がサイト全体に影響すべてのコードで常に session_start をグレップ
ページネーション非使用クエリの no_found_rows を無視小さい最適化だが積み重なる警告ではなく情報としてフラグ
共有ホスティングでのオブジェクトキャッシュを推奨多くの共有ホストは永続キャッシュを欠落ホスティング環境を最初に確認
PHP のみを確認し JS ポーリングを見落とすJS setInterval + fetch = Self-DDoSポーリングパターン用の .js ファイルを確認

詳細リファレンス

タスクに基づいてこれらのリファレンスをロード:

タスクロードするリファレンス
PHP コードの問題確認references/anti-patterns.md
WP_Query 呼び出しの最適化references/wp-query-guide.md
キャッシング実装references/caching-guide.md
高トラフィックイベント準備references/measurement-guide.md

注記: 標

ライセンス: MIT(寛容ライセンスのため全文を引用しています) · 原本リポジトリ

詳細情報

作者
jorgerosal
リポジトリ
jorgerosal/wordpress-skills
ライセンス
MIT
最終更新
2026/4/17

Source: https://github.com/jorgerosal/wordpress-skills / ライセンス: MIT

本サイトは GitHub 上で公開されているオープンソースの SKILL.md ファイルをクロール・インデックス化したものです。 各スキルの著作権は原作者に帰属します。掲載に問題がある場合は info@alsel.co.jp または /takedown フォームよりご連絡ください。
原作者: jorgerosal · jorgerosal/wordpress-skills · ライセンス: MIT