Товар добавляется, счётчик корзины растёт — а страница оформления говорит, что корзина пуста. Самая частая причина не кэш, а плагин скорости, откладывающий JavaScript, от которого зависит блочное оформление.
Блочные корзина и оформление WooCommerce зависят от объекта wp и пакетов скриптов wp-*. Когда плагин скорости откладывает все скрипты без исключений, эти пакеты выполняются в неверном порядке, в консоли возникает wp is not defined, и блок отрисовывает состояние пустой корзины. Решение — исключить скрипты ядра WordPress и блоков WooCommerce из правила отложенной загрузки, а не чистить корзину или кэш.
Последние два пункта важны. У администратора проблема не видна, потому что большинство плагинов скорости отключают оптимизацию для авторизованных пользователей. Владелец сайта узнаёт о сбое позже всех: он происходит только у реальных клиентов.
Общая ошибка — искать проблему на сервере. Сервер знает корзину правильно, доказательство — растущий счётчик.
Откройте страницу оформления без авторизации (в приватном окне) и посмотрите в консоль браузера.
Uncaught ReferenceError: wp is not defined
at checkout-blocks.js:1
Uncaught TypeError: Cannot read properties of undefined (reading 'createElement')
Если эти строки есть, диагноз поставлен. Корзина в порядке, сервер в порядке; JavaScript, который рисует страницу, умирает до запуска.
Дополнительная проверка: посмотрите теги <script> в исходном коде. Если скрипты ядра (wp-polyfill, wp-element, wp-data) тоже помечены defer, причина подтверждена.
Скрипты WordPress зависят друг от друга, и этот порядок объявляется через wp_enqueue_script. Обычно браузер его сохраняет.
Атрибут defer заставляет скрипты выполняться после разбора HTML. Спецификация говорит, что отложенные скрипты выполняются в порядке документа, но при динамически добавляемых скриптах, условной загрузке и встроенном коде эта гарантия на практике ломается. В частности:
<script>. Этот код выполняется сразу, а wp-element, от которого он зависит, отложен. Порядок инвертируется.Результат: код, обращающийся к wp, выполняется до его определения, выбрасывает ошибку, и блок на React не монтируется. Не смонтировавшись, он показывает состояние по умолчанию — пустую корзину.
Когда я доводил эту ошибку до первопричины на реальном сайте, источником оказалось правило сплошного defer во вспомогательном плагине темы: несколько строк, добавлявших defer всем скриптам сайта без списка исключений.
add_filter( 'script_loader_tag', function ( $tag, $handle ) {
// Идентификаторы, которые нельзя откладывать
$skip_prefixes = array( 'wp-', 'wc-', 'woocommerce' );
$skip_exact = array( 'jquery', 'jquery-core', 'jquery-migrate' );
foreach ( $skip_prefixes as $prefix ) {
if ( 0 === strpos( $handle, $prefix ) ) {
return $tag;
}
}
if ( in_array( $handle, $skip_exact, true ) ) {
return $tag;
}
// На корзине и оформлении не откладываем ничего
if ( function_exists( 'is_checkout' ) && ( is_checkout() || is_cart() ) ) {
return $tag;
}
if ( false !== strpos( $tag, ' defer' ) || false === strpos( $tag, ' src=' ) ) {
return $tag;
}
return str_replace( ' src=', ' defer src=', $tag );
}, 10, 2 );
При использовании готового плагина та же логика применяется через его настройки: в разделе отложенной загрузки/объединения JavaScript есть список исключений. Добавьте туда идентификаторы, начинающиеся на wp-, wc- и woocommerce, и по возможности полностью исключите корзину и оформление из оптимизации.
wp is not defined обязан исчезнуть.«Ваша корзина пуста» — обычно не ошибка корзины, а ошибка порядка загрузки скриптов. Сервер знает корзину; JavaScript, который её нарисует, не может запуститься.
Общее правило: оптимизация скорости не применяется без исключений. Сплошные правила откладывания, объединения или задержки должны исключать скрипты ядра WordPress и платёжный процесс. Ценой скорости не должны быть продажи.
Сервер почти наверняка знает корзину верно, но JavaScript, который её отрисовывает, не может выполниться. Блочные корзина и оформление зависят от объекта wp; когда плагин скорости откладывает все скрипты, объект не определяется вовремя, и блок рисует себя как пустую корзину.
Потому что большинство плагинов скорости отключают кэширование и оптимизацию скриптов для авторизованных пользователей. Просматривая сайт администратором, вы не получаете оптимизации и не видите ошибки. Поэтому тестировать нужно в приватном окне, без авторизации.
Нет. Может показаться, что помогло, потому что при первой загрузке меняется тайминг скриптов, но проблема вскоре возвращается. Постоянное решение — добавить в правило откладывания список исключений для скриптов ядра WordPress и WooCommerce.
Не нужно. Откладывание даёт реальный выигрыш на страницах вне платёжного процесса. Важно не применять его без исключений: освободить скрипты с префиксами wp-, wc- и woocommerce и полностью отключить оптимизацию на корзине и оформлении.