Ajax занимает в 10 раз больше времени, чем должен/мог бы
Я только что столкнулся с первой серьезной проблемой в WordPress, и как человеку, который любит работать с Ajax, это кажется существенным.
У меня есть Ajax-запрос, который выполняется 1.5 секунды при использовании Ajax API WordPress.
Если я беру точно такой же код и запускаю его с помощью собственного скрипта (без WordPress), Ajax-запрос выполняется всего за 150 миллисекунд. Это не преувеличение
Если посмотреть на самый первый комментарий в http://wp.smashingmagazine.com/2011/10/18/how-to-use-ajax-in-wordpress/ и последующее обсуждение, вы увидите, что эта медлительность вызвана тем, что при каждом запросе загружается весь WordPress...
Я надеюсь, что существует решение, которое позволит выполнять Ajax-запросы без загрузки всего WordPress.
Каков ваш опыт по ускорению Ajax-запросов в WordPress?

Да, это неприятная проблема — для полной загрузки окружения WordPress требуется значительное время.
Мне понадобилась гораздо лучшая производительность (для очень динамичного поиска с инкрементальным выводом результатов), и вот что я сделал:
- Создал пользовательский файл в качестве обработчика Ajax.
- Использовал константу SHORTINIT для ограниченной загрузки ядра WordPress.
- Очень избирательно подгружал только те части ядра, которые действительно нужны для задачи.
Это обеспечивает сильно ограниченное окружение, но производительность становится значительно лучше, при этом сохраняется разумная степень совместимости с WordPress (начиная с $wpdb
).
Вот начало моего загрузочного файла — выглядит не идеально, но работает для конкретных нужд:
<?php
ini_set('html_errors', 0);
define('SHORTINIT', true);
require '../../../../wp-load.php';
require( ABSPATH . WPINC . '/formatting.php' );
require( ABSPATH . WPINC . '/meta.php' );
require( ABSPATH . WPINC . '/post.php' );
wp_plugin_directory_constants();
// здесь будет основной код

Что вы подразумеваете под константой SHORTINIT? Можете привести примеры? Я предполагаю, что мне нужно будет настроить собственные обработчики с разной степенью загрузки WP в зависимости от потребностей запроса, но хотелось бы увидеть примеры, которые вы создали.

@Mike это не широко известно, но концепция очень проста - если константа SHORTINIT
установлена, WP не будет загружать большую часть ядра (нет большинства API/функций, нет плагинов, нет темы). Я добавлю код для ответа.

Выглядит нормально. Мне просто не нравится факт, что приходится использовать require '../../../../wp-load.php'; это делает решение довольно кастомным. Также беспокоит, насколько легко можно подтянуть именно те ресурсы, которые "нужны", потому что по моему опыту WordPress не очень модульный.

@Mike верно, но даже с проблемами это намного лучше, чем конечная точка, которая вообще ничего не знает о WP. Это можно (и нужно) еще улучшить, но на данный момент для меня это не срочная задача.

Есть ли какие-нибудь методы определения местоположения wp-load.php изнутри WordPress? Например, могу ли я записать статический файл с установленным путем как переменную внутри него при загрузке плагина, а затем включить этот файл в автономный файл ответа Ajax?

@hereswhatidid да, это один из вариантов, вы можете использовать, например, get_included_files()
PHP. Однако обратите внимание, что запись в директорию плагина — не самая лучшая практика, обычно записи в файловую систему должны производиться только в директорию контента. Это та проблема, которую не так сложно настроить для себя, но довольно сложно создать решение, подходящее для публичного кода.

@Rarst, вместо require '../../../../wp-load.php';
я думаю, что лучше использовать что-то вроде: $dir = explode ( 'wp-content', dirname(__FILE__) );
и затем require $dir[0] . 'wp_load.php'
? Я считаю, что это более гибко и может использоваться повсеместно в теме или плагине

@G.M. папка content может быть свободно перемещена, это ошибочное предположение, что код выполняется внутри корневой директории. Как указано выше - это сложно обработать универсальным способом.

@Rarst, конечно, папка content может быть перемещена, но если это так, ваше решение тоже может не сработать, или я ошибаюсь? Если в моем плагине (или теме) у меня есть файл options.php
, где я определяю define('WPCONTENTROOTFOLDER', 'wp-content')
и затем $dir = explode ( WPCONTENTROOTFOLDER, dirname(__FILE__) )
, это будет работать в 90% случаев, а для остальных я напишу в документации плагина, что нужно изменить, если папка content перемещена. Например, я могу реализовать другую константу 'FULLWPCONTENTFOLDER', обычно пустую, но если она задана, плагин будет использовать её.

@G.M. моё решение специфично для моей установки, оно не предназначено для распространяемого кода. Ваш код просто захардкожен с другими (более общими относительно, я согласен) предположениями, но лично я не считаю, что он соответствует уровню распространяемого кода.

@Rarst (последнее, честно) Да, возможно мой код не распространяемый (конечно не для репозитория WP и/или большой аудитории), но я считаю его переиспользуемым кодом, хотя бы для себя: на данный момент у меня более 20 клиентских установок WP онлайн, и во всех есть плагины, разработанные мной, поэтому писать легко переиспользуемый код жизненно необходимо для меня, даже если это не распространяемый код.

Я использовал форкнутую (приватную) версию этого плагина с GitHub: http://github.com/EkAndreas/ajaxflow/

Я нашел это, и это ускорило мой ajax.
function my_deregister_heartbeat() {
global $pagenow;
if ( 'post.php' != $pagenow && 'post-new.php' != $pagenow ) {
wp_deregister_script('heartbeat');
wp_register_script('heartbeat', false);
}
}
add_action( 'admin_enqueue_scripts', 'my_deregister_heartbeat' );
