HUSKY - Products Filter Professional for WooCommerce

Оптимизация производительности: ленивая загрузка slideout для больших иерархий категорий

Когда у вас есть родительская категория с:

  • Большим количеством товаров (500-1000+)
  • Глубокой иерархией категорий (несколько уровней подкатегорий)
  • Включённым Dynamic Recount

Фильтр товаров может генерировать сотни SQL-запросов при каждой загрузке страницы, даже если пользователь никогда не использует фильтр. Это приводит к:

  • Медленной загрузке страницы (10+ секунд)
  • Ошибкам 504 Gateway Timeout
  • Высокой нагрузке на сервер
  • Плохому пользовательскому опыту

Почему это происходит

При включённом Dynamic Recount WOOF должен:

  1. Рекурсивно обрабатывать все дочерние категории
  2. Выполнять SQL-запросы для каждого термина, чтобы подсчитать товары
  3. Вычислять количество с учётом контекста текущей категории

Пример: Категория “Sunglasses” с подкатегориями (Men → Women → Shapes → Brands) создаёт огромную нагрузку запросами.

Традиционные решения (недостаточно)

Скрытие slideout правилами CSS/display — Фильтр всё равно обрабатывается на сервере
Отключение Dynamic Recount — Теряется важная функциональность
Удаление опций фильтра — Пользователи не могут правильно фильтровать
Индексы базы данных — Небольшое улучшение, не решает корневую причину

Оптимальное решение: ленивая загрузка slideout

Ключевая идея: Загружать фильтр ТОЛЬКО когда пользователь действительно открывает slideout.

✅ Страница загружается мгновенно (без обработки фильтра)
✅ Фильтр работает идеально, когда нужен
✅ Никаких лишних затрат ресурсов сервера
✅ Идеально для ботов и случайных посетителей
✅ Сохраняет всю функциональность фильтра

Реализация

Добавьте следующий код в 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. Отключите текущий slideout в настройках WOOF, если он включён
  2. Добавьте код выше в functions.php вашей активной темы
  3. Оставьте включёнными следующие настройки WOOF:
    • Cache dynamic recount: Yes
    • Cache terms: Yes
    • Hide empty terms: Yes
    • Dynamic Recount: Yes
  4. Опциональная настройка:
    • Настройте ширину slideout: измените width: 350px и right: -350px
    • Измените положение кнопки: измените top: 50%
    • Настройте цвета: обновите значения background и color
    • Чтобы работало по всему сайту: удалите условие if (!is_product_category())

Как это работает

  1. Загрузка страницы: Рендерится только кнопка-триггер (без обработки фильтра)
  2. Пользователь нажимает кнопку: Slideout открывается, появляется оверлей
  3. Только при первом открытии: JavaScript автоматически нажимает скрытую кнопку “Start Filtering”
  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);
}

Slideout слева:

Измените эти значения:

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

Когда использовать это решение

Используйте ленивую загрузку slideout, когда:

  • У категории глубокая иерархия (3+ уровня)
  • 500+ товаров в категории
  • Требуется Dynamic Recount
  • Время загрузки страницы > 5 секунд
  • Возникают таймауты 504

Альтернатива для фильтра в сайдбаре

Если предпочитаете сайдбар вместо slideout, используйте:

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

Это создаёт кнопку “Start Filtering” в сайдбаре, которая загружает фильтр по нажатию.


Это решение обеспечивает наилучший баланс между производительностью и функциональностью, гарантируя быструю загрузку страниц при сохранении полных возможностей фильтрации для тех пользователей, которым они нужны.

Ссылка: https://pluginus.net/support/topic/performance-issue-504-timeouts-on-parent-category-with-deep-hierarchy-flatsome-theme/