Почему ваш CS-Cart «летает» в тестах, но заставляет первых покупателей ждать по 10 секунд

Я ненавижу синтетические тесты скорости. И вот почему.

Пару лет назад мы сдавали крупный проект на CS-Cart. Премиальная косметика, около 18 500 товаров, куча категорий, красивые сочные фотографии. Мы вылизали код, настроили Redis, переехали на дорогой VPS с быстрыми NVMe-дисками. Показываем клиенту отчеты: Lighthouse горит зеленым, TTFB (время до первого байта) — микроскопические 120 миллисекунд. Все довольны, подписываем акты.

А через три дня в десять вечера мне звонит владелец магазина. Голос дрожит от злости. «Зайди в категорию "Шампуни для объема", — говорит он. — Я ждал загрузки ровно 12 секунд. Какое, к черту, ускорение?»

Я открываю ноутбук, перехожу по ссылке. Страница открывается мгновенно. Кликаю на другую категорию — опять мгновенно. Я пытаюсь объяснить ему, что, возможно, у него просел интернет. Но клиент непреклонен: он тестировал с трех разных устройств и разных провайдеров. Первое посещение новой категории — это всегда адская, мучительная задержка.

Тогда я впервые по-настоящему глубоко закопался в то, как устроена работа с изображениями в этой CMS. И понял, что стандартная оптимизация cs-cart магазина часто лечит симптомы, но полностью игнорирует реальный опыт живого покупателя.

Анатомия невидимого тормоза: ленивая генерация

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

Когда вы импортируете товары в CS-Cart или просто загружаете новые фото через админку, движок не нарезает их сразу под все нужные размеры. Он сохраняет только один исходник — огромный, тяжелый оригинал. Сетка категории требует миниатюр размером, например, 250 на 250 пикселей. Но физически этих файлов на сервере еще нет.

Они создаются в тот самый момент, когда первый пользователь заходит на страницу.

Представьте картину. Покупатель открывает категорию, где выводится 48 товаров. CS-Cart понимает, что миниатюр для этих позиций на диске нет. Вместо того чтобы просто отдать готовую страницу, сервер начинает судорожно работать. Он берет 48 оригинальных тяжелых изображений, запускает библиотеку GD или Imagick и начинает по очереди пережимать, масштабировать и сохранять каждый файл. Все это происходит в один поток, в рамках одного PHP-запроса.

Процессор сервера загружается на 100%. База данных ждет. А ваш покупатель смотрит на белый экран. Для него это выглядит как классическая cs-cart медленная загрузка категорий.

Как только этот адский круг завершается, картинки сохраняются в кэш. Второй, третий и сотый посетители получат страницу за долю секунды. Но первый — тот самый, который пришел покупать и принес вам деньги — уже закрыл вкладку и ушел к конкурентам.

Почему стандартные методы «ускорения» здесь бессильны?

Обычно разработчики предлагают стандартный набор: «давайте настроим кэширование страниц», «давайте поставим Varnish» или «подключим CDN». В данном сценарии все это — мертвому припарка.

Полностраничное кэширование не спасет, потому что кэш страницы нельзя построить, пока PHP не закончит генерировать изображения. CDN (сеть доставки контента) тоже не поможет. CDN запрашивает картинку у вашего сервера, а тот отвечает ему с задержкой в 10 секунд, потому что процессор занят ресайзом. В итоге CDN просто отдает ошибку 504 Gateway Timeout.

Каждый раз, когда вы делаете импорт товаров, обновляете остатки через 1С или просто чистите кэш из админки (а это в CS-Cart приходится делать регулярно), ваши покупатели снова и снова становятся бесплатными тестировщиками, которые своей болью генерируют вам картинки.

Я считаю это архитектурным провалом, который нужно лечить принудительно.

Как решить проблему раз и навсегда

Решение здесь только одно: сервер должен генерировать миниатюры ДО того, как на страницу зайдет первый человек. Кэш должен быть «прогрет».

Мы перепробовали разные подходы. Пробовали использовать стандартные краулеры, которые имитируют обход сайта роботом. Но обычный парсинг страниц — это слишком медленно и создает дикую нагрузку на сервер, ведь он все равно дергает весь тяжелый PHP-каркас движка.

Правильный путь — это низкоуровневый генератор. Нужен скрипт, который работает напрямую с базой данных и файловой системой через консоль (CLI). Он берет список всех товаров, находит оригиналы изображений, сопоставляет их с настройками размеров вашей темы и генерирует всю сетку миниатюр в фоновом режиме. Без участия браузера. Без создания нагрузки на веб-сервер, который в это время обслуживает реальных клиентов.

Когда мы внедрили такой подход на проекте той самой косметики, время первой загрузки категорий после очистки кэша упало с 12 секунд до стабильных 0.4 секунды. Клиент перестал терять заказы после утренней синхронизации базы данных.

Если вы устали от того, что ваш магазин периодически «залипает» на ровном месте, а пользователи жалуются на долгий отклик, не спешите покупать более дорогой хостинг. Скорее всего, дело именно в изображениях. Мы в GuardLabs собаку съели на решении подобных неочевидных проблем производительности. Наша услуга Прогрев кэша миниатюр в CS-Cart создана как раз для того, чтобы навсегда избавить ваш сайт от эффекта «первого визита» и сделать загрузку стабильно быстрой для каждого клика.