Оптимизация шорткодов WordPress: ускоряем вывод до 5 секунд

a close up of a typewriter with the word wordpress printed on it

Введение

Шорткоды – мощный инструмент WordPress, позволяющий вставлять динамический контент без написания кода в постах. Однако каждый вызов шорткода добавляет нагрузку на PHP‑парсер и базу данных. В этой статье мы разберём, как ускорить работу шорткодов, используя кэширование, удаление лишних, оптимизацию парсинга и замену их на блоки Gutenberg.

Кеширование вывода шорткодов

Самый простой способ снизить нагрузку – сохранять готовый HTML в кеш. WordPress предоставляет API set_transient(), которое удобно использовать для короткоживущего кэша.

Пример кэширования с помощью транзиентов

function my_shortcode_cached( $atts ) { $key = 'my_shortcode_'. md5( serialize( $atts ) ); $cached = get_transient( $key ); if ( false!== $cached ) { return $cached; // Возврат из кеша без выполнения логики } // Трудоёмкая логика шорткода $output = '
‘. my_heavy_query( $atts ). ‘

‘; // Сохраняем результат на 12 часов set_transient( $key, $output, 12 * HOUR_IN_SECONDS ); return $output; } add_shortcode( ‘my_cached’, ‘my_shortcode_cached’ );

Для более надёжного кеша на уровне сервера можно воспользоваться Redis объектным кешем. В этом случае set_transient() автоматически использует Redis, если он подключён.

Удаление ненужных шорткодов

Со временем сайт может собрать десятки шорткодов, которые больше не используются. Каждый из них всё равно регистрируется в глобальном массиве $shortcode_tags и участвует в парсинге.

Как найти «мертвые» шорткоды

  • Сканируйте контент базы с помощью LIKE "%[shortcode_name%".
  • Сравните список найденных шорткодов с теми, что зарегистрированы через add_shortcode().

Автоматическое удаление

function remove_unused_shortcodes() { global $shortcode_tags; $used = []; $posts = get_posts( [ 'numberposts' => -1, 'post_type' => 'any', 'post_status' => 'publish' ] ); foreach ( $posts as $post ) { preg_match_all( '/[([a-z0-9_]+)(s|])/i', $post->post_content, $matches ); $used = array_merge( $used, $matches[1] ); } $used = array_unique( $used ); foreach ( $shortcode_tags as $tag => $func ) { if (! in_array( $tag, $used ) ) { remove_shortcode( $tag ); } } } add_action( 'init', 'remove_unused_shortcodes' );

После очистки парсер обрабатывает только реально используемые шорткоды, экономя до 30% CPU.

Оптимизация парсинга шорткодов

WordPress парсит контент каждый раз, вызывая do_shortcode(). Можно сократить объём работы, отключив парсинг в местах, где он не нужен.

Отключаем шорткоды в excerpt и RSS

remove_filter( 'the_excerpt', 'do_shortcode' ); remove_action( 'rss2_item', 'do_shortcode' );

Если ваш сайт использует кастомные типы записей, проверьте, где именно вызывается the_content, и добавьте условие.

Lazy‑парсинг через фильтр

Создайте фильтр, который будет заменять шорткоды на плейсхолдеры, а реальный вывод выполнять только при первом просмотре пользователем.

function lazy_shortcode_placeholder( $content ) { return preg_replace_callback( '/[my_slow_shortcode(.*?)]/', function( $m ) { return '

‘; }, $content ); } add_filter( ‘the_content’, ‘lazy_shortcode_placeholder’, 5 ); function render_lazy_shortcode() { if (! is_user_logged_in() ) return; // AJAX‑запрос к серверу, который возвращает уже кешированный HTML } add_action( ‘wp_footer’, ‘render_lazy_shortcode’ );

Такой подход часто используют в сочетании с CDN, как описано в статье про микро‑кэширование WordPress.

Замена шорткодов на блоки Gutenberg

Начиная с WP 5.0, редактор блоков позволяет избавиться от большинства шорткодов. Блоки рендерятся на стороне сервера один раз и могут кешироваться через render_block.

Создание простого динамического блока

function register_my_dynamic_block() { wp_register_script( 'my-block-editor', plugins_url( 'block.js', __FILE__ ), array( 'wp-blocks', 'wp-element', 'wp-editor' ), filemtime( plugin_dir_path( __FILE__ ). 'block.js' ) ); register_block_type( 'my/plugin-dynamic', array( 'editor_script' => 'my-block-editor', 'render_callback' => 'my_dynamic_block_render', ) ); } add_action( 'init', 'register_my_dynamic_block' ); function my_dynamic_block_render( $attributes ) { // Можно воспользоваться тем же кешем, что и для шорткода return my_shortcode_cached( $attributes ); }

После миграции вы избавляетесь от парсинга шорткода полностью, а блок автоматически использует кеш, если он включён.

Инструменты мониторинга производительности

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

  • Cloudflare Magic Transit – защита от DDoS и ускорение доставки кеша.
  • Плагин Query Monitor покажет количество вызовов do_shortcode() на каждой странице.
  • Для CI/CD используйте GitHub Actions и проверяйте время генерации HTML в тестах.

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

Заключение

Оптимизация шорткодов – это сочетание трёх простых шагов: кэшировать вывод, удалять неиспользуемые шорткоды и заменять их на блоки. При правильной реализации вы сможете сократить время генерации страниц на 40‑70%, снизить нагрузку на сервер и улучшить пользовательский опыт. Не забывайте про мониторинг и постепенный переход к блокам, чтобы ваш сайт оставался быстрым и безопасным.

❓ Часто задаваемые вопросы

Как быстро проверить, какие шорткоды реально используются?

Запустите SQL‑запрос с оператором LIKE «%[shortcode_name%» по таблице wp_posts и сравните найденные имена со списком, полученным через глобальный массив $shortcode_tags.

Можно ли кэшировать шорткод без плагина Redis?

Да, используйте WordPress Transients API – он сохраняет данные в базе, а при наличии объектного кеша (Memcached, APCu) автоматически переключится на более быстрый слой.

Стоит ли полностью отключать do_shortcode() в excerpt?

Если в кратком описании нет шорткодов, отключение безопасно и уменьшит количество парсинга примерно на 15‑20%.

Как мигрировать сложный шорткод в блок Gutenberg?

Создайте динамический блок через register_block_type, укажите render_callback, который вызывает прежнюю функцию шорткода, и удалите сам шорткод из контента.