HUSKY - Product Filter for WooCommerce

大規模なWooCommerceカテゴリーフィルターを高速化:遅延読み込みスライドアウト

親カテゴリーに以下の条件がある場合:

  • 大量の商品(500~1000以上)
  • 深いカテゴリー階層(複数レベルのサブカテゴリー)
  • 動的再カウントが有効

商品フィルターは、ユーザーがフィルターを使用しなくても、ページ読み込みごとに数百のSQLクエリを生成する可能性があります。これにより、次の問題が発生します:

  • ページ読み込みの遅延(10秒以上)
  • 504 Gateway Timeout エラー
  • サーバー負荷の増大
  • ユーザーエクスペリエンスの低下

なぜこれが発生するのか

動的再カウントが有効な場合、WOOFは以下を行う必要があります:

  1. すべての子カテゴリーを再帰的に処理する
  2. 各タームに対して商品をカウントするSQLクエリを実行する
  3. 現在のカテゴリーコンテキストを考慮してカウントを計算する

例:“サングラス”カテゴリーにサブカテゴリー(メンズ→ウィメンズ→形状→ブランド)がある場合、大量のクエリ負荷が発生します。

従来の解決策(不十分)

CSS/表示ルールでスライドアウトを非表示にする – フィルターはサーバー上で依然として処理される
動的再カウントを無効にする – 重要な機能が失われる
フィルターオプションを削除する – ユーザーが適切にフィルタリングできない
データベースインデックス – わずかな改善に過ぎず、根本原因を解決しない

最適な解決策:遅延読み込みスライドアウト

重要なコンセプト:ユーザーが実際にスライドアウトを開いたときのみフィルターを読み込む。

✅ ページが瞬時に読み込まれる(フィルター処理なし)
✅ 必要なときにフィルターが完全に動作する
✅ サーバーリソースを無駄にしない
✅ ボットやカジュアルブラウザに最適
✅ すべてのフィルター機能をそのまま保持

実装

次のコードをテーマの functions.php に追加します:

/**
 * WOOF Lazy-Load Slideout Filter
 * Loads filter only when user clicks to open slideout
 * Solves performance issues with deep category hierarchies
 */
add_action('wp_footer', function () {
    // Only on product category pages (optional - remove condition to show everywhere)
    if (!is_product_category()) {
        //return;
    }
    ?>

    <!-- Slideout Trigger Button -->
    <div id="woof-slideout-trigger" style="position: fixed; right: 0; top: 50%; transform: translateY(-50%); z-index: 9999; cursor: pointer; background: #333; color: #fff; padding: 15px 10px; border-radius: 5px 0 0 5px; font-weight: bold; writing-mode: vertical-rl; text-orientation: mixed;">
        FILTERS
    </div>

    <!-- Slideout Panel -->
    <div id="woof-slideout-panel" style="position: fixed; right: -350px; top: 0; width: 350px; height: 100%; background: #fff; box-shadow: -2px 0 10px rgba(0,0,0,0.3); z-index: 9998; transition: right 0.3s ease; overflow-y: auto; padding: 20px;">
        
        <!-- Close Button -->
        <div style="text-align: right; margin-bottom: 15px;">
            <span id="woof-slideout-close" style="cursor: pointer; font-size: 24px; font-weight: bold;">✖</span>
        </div>

        <!-- WOOF Filter with autohide - loads only on first click -->
        <?php echo do_shortcode('[woof autohide=0 start_filtering_btn=1]'); ?>
    </div>

    <!-- Background Overlay -->
    <div id="woof-slideout-overlay" style="position: fixed; top: 0; left: 0; width: 100%; height: 100%; background: rgba(0,0,0,0.5); z-index: 9997; display: none;"></div>

    <script>
        jQuery(document).ready(function ($) {
            var $trigger = $('#woof-slideout-trigger');
            var $panel = $('#woof-slideout-panel');
            var $overlay = $('#woof-slideout-overlay');
            var $close = $('#woof-slideout-close');
            var filterLoaded = false;

            // Open slideout
            $trigger.on('click', function () {
                $panel.css('right', '0');
                $overlay.fadeIn(300);

                // Auto-trigger WOOF "Start Filtering" button on first open
                if (!filterLoaded) {
                    setTimeout(function () {
                        var $woofBtn = $('.woof_start_filtering_btn');
                        if ($woofBtn.length) {
                            $woofBtn.trigger('click');
                            // Hide the button after triggering
                            $woofBtn.hide();
                            filterLoaded = true;
                        }
                    }, 500);
                }
            });

            // Close slideout
            function closeSlideout() {
                $panel.css('right', '-350px');
                $overlay.fadeOut(300);
            }

            $close.on('click', closeSlideout);
            $overlay.on('click', closeSlideout);
        });
    </script>

    <?php
}, 999);

設定手順

  1. 有効になっている場合、WOOF設定で現在のスライドアウトを無効にします
  2. アクティブなテーマの functions.php上記のコードを追加します
  3. 以下のWOOF設定を有効にしたままにします:
    • 動的再カウントのキャッシュ:はい
    • タームのキャッシュ:はい
    • 空のタームを非表示:はい
    • 動的再カウント:はい
  4. オプションのカスタマイズ:
    • スライドアウト幅の調整:width: 350pxright: -350px を変更
    • ボタン位置の変更:top: 50% を修正
    • 色のカスタマイズ:backgroundcolor の値を更新
    • サイト全体で動作させる:if (!is_product_category()) 条件を削除

動作の仕組み

  1. ページ読み込み時:トリガーボタンのみがレンダリングされる(フィルター処理なし)
  2. ユーザーがボタンをクリック:スライドアウトが開き、オーバーレイが表示される
  3. 初回のみ:JavaScriptが非表示の“フィルタリング開始”ボタンを自動クリックする
  4. フィルター読み込み:WOOFがすべてのクエリを処理し、フィルターオプションを表示する
  5. 以降の開封:フィルターは既に読み込まれており、瞬時に開く

実際の結果

改善前:

  • ページ読み込み:10~15秒(または504タイムアウト)
  • ページビューあたり500以上のSQLクエリ
  • 直帰率が高い

改善後:

  • ページ読み込み:< 2秒
  • フィルター読み込み:約3秒(リクエスト時のみ)
  • サーバー負荷が約50%削減(多くのユーザーはフィルターを開かないため)

互換性

✅ すべてのWOOFバージョンで動作
✅ ページキャッシュ(WP Rocket、LiteSpeedなど)と互換性あり
✅ モバイルフレンドリー
✅ 任意のWordPressテーマで動作

高度なカスタマイズ

テーマのスタイルに合わせる:

/* Add to your theme's CSS */
#woof-slideout-trigger {
    background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
    font-family: 'Your Theme Font', sans-serif;
    letter-spacing: 2px;
}

#woof-slideout-panel {
    background: #f8f9fa;
    font-family: 'Your Theme Font', sans-serif;
}

#woof-slideout-trigger:hover {
    transform: translateY(-50%) scale(1.05);
}

左側スライドアウト:

次の値を変更します:

right: -350px  →  left: -350px
right: 0       →  left: 0
right: -350px  →  left: -350px

このソリューションを使用するタイミング

遅延読み込みスライドアウトは以下の場合に使用します:

  • カテゴリーに深い階層がある(3レベル以上)
  • カテゴリー内に500以上の商品がある
  • 動的再カウントが必要
  • ページ読み込み時間が5秒を超える
  • 504タイムアウトが発生している

サイドバーフィルターの代替

スライドアウトの代わりにサイドバーを希望する場合は、以下を使用します:

echo do_shortcode('[woof autohide=1 start_filtering_btn=1]');

これにより、サイドバーに“フィルタリング開始”ボタンが作成され、クリック時にフィルターが読み込まれます。


このソリューションは、パフォーマンス機能性の最適なバランスを提供し、高速なページ読み込みを確保しながら、必要なユーザーに完全なフィルタリング機能を維持します。

参考: https://pluginus.net/support/topic/performance-issue-504-timeouts-on-parent-category-with-deep-hierarchy-flatsome-theme/