Чому 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;