Почему WooCommerce работает медленно
WooCommerce добавляет десятки AJAX-запросов, корзину и сессии — всё это нельзя кэшировать стандартными методами. Нужен особый подход.
Отключение ненужных скриптов
// functions.php — убираем скрипты 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');
}
}, 99);
Оптимизация изображений
| Инструмент | Метод | Снижение размера |
|---|---|---|
| ShortPixel | WebP + сжатие | 60–80% |
| Imagify | WebP + AVIF | 50–75% |
| cwebp CLI | WebP вручную | 40–70% |
Индексы базы данных для WooCommerce
-- Ускорение запросов к мета товаров
ALTER TABLE wp_postmeta ADD INDEX meta_key_value (meta_key, meta_value(20));
-- Ускорение истории заказов
ALTER TABLE wp_woocommerce_order_items ADD INDEX order_item_type (order_item_type);
Разбор типичных ошибок WooCommerce
Специфика WooCommerce в том, что проблемы производительности проявляются не на витрине, а именно там, где идут деньги: в корзине и на checkout. Ошибка на витрине теряет посетителя, ошибка на checkout теряет уже почти оплаченный заказ — поэтому диагностику стоит начинать именно с платёжной цепочки.
| Текст ошибки или симптом | Причина | Что делать |
|---|---|---|
| Error establishing a database connection на checkout при пиковой нагрузке | Исчерпан лимит одновременных соединений MySQL из-за множества AJAX-запросов корзины | Поднять max_connections и включить кэш фрагментов только для неавторизованных гостей |
| There has been a critical error on this website после обновления WooCommerce | Конфликт версии темы или платёжного плагина с новым API WooCommerce | Откатить обновление на staging и смотреть wp-content/debug.log |
| 500 ошибка на /wp-json/wc/store/cart | REST API WooCommerce блокируется правилом WAF или security-плагина по паттерну wp-json | Добавить исключение для /wp-json/wc/ в правилах фаервола |
| Корзина показывает чужие товары после включения кэша | Полный кэш страниц веб-сервера закэшировал HTML корзины с данными одного из посетителей | Исключить /cart/, /checkout/ и /my-account/ из зоны кэширования |
Если проблема упирается именно в лимит соединений к базе — см. статью про MySQL: too many connections.
Когда обычная оптимизация не спасёт
- Каталог свыше 5000 товаров с фильтрами по атрибутам — MySQL LIKE-запросы к таким объёмам не масштабируются, нужен внешний поиск вроде Elasticsearch
- Больше 50 одновременных заказов в минуту в распродажу — один пул PHP-FPM не справится, нужна очередь фоновых заданий и несколько воркеров
- Мультивалютность и мультисклад через сторонние надстройки — они добавляют собственные тяжёлые запросы, которые не лечатся индексами из этой статьи
- Хостинг с сетевым диском под wp-content/uploads — операции ввода-вывода будут медленными независимо от кэша и индексов
- Подписочная модель с ежедневными автосписаниями у тысяч клиентов — крон WordPress (wp-cron) на обычном хостинге ненадёжен под такой нагрузкой, нужен системный cron
Отдельно стоит проверить хостинг на количество ядер CPU. WooCommerce — это в первую очередь PHP-нагрузка на каждый AJAX-запрос корзины, и без запаса по CPU даже правильные индексы не спасут от очередей в PHP-FPM в момент распродажи.
Исключение критичных страниц из кэша
Полный HTML-кэш нельзя применять к динамическим страницам магазина. На уровне веб-сервера это делается явным исключением по пути:
location ~* ^/(cart|checkout|my-account)/ {
proxy_no_cache 1;
proxy_cache_bypass 1;
}
Для повторяющихся частей внутри самих этих страниц (например, блока рекомендаций) используйте объектный кэш — см. статью про Redis для WordPress, а не кэш страниц целиком.
Проверка производительности магазина
- TTFB страницы checkout должен оставаться стабильным при 10+ параллельных тестовых сессиях
- Плагин Query Monitor показывает число SQL-запросов на страницу товара — больше 100 запросов означает проблему в теме или надстройках
- После добавления индексов EXPLAIN на медленный запрос должен показывать использование ключа, а не full table scan
- Waterfall в GTmetrix для /cart/ не должен содержать запросов дольше 500 мс к своему домену
-- Проверить, что индекс действительно используется
EXPLAIN SELECT * FROM wp_postmeta
WHERE meta_key = '_stock' AND meta_value < 10;
SHOW INDEX FROM wp_woocommerce_order_items;