Сделайте WordPress WP-API быстрее, не загружая тему и плагины

Я хотел бы сделать запросы к WordPress API намного быстрее. Мой API реализован в плагине (с помощью register_rest_route для регистрации моих маршрутов). Однако, поскольку это плагин, все загружается с ним (дочерняя тема и тема), и в основном запрос к этому API занимает половину секунды из-за загрузки всех этих бесполезных частей.

Разве WordPress API не может использоваться по-другому? Поскольку для большинства плагинов, использующих WP-API, не нужны никакие другие плагины для загрузки, тем более тема … Я не понимаю, как они могли это пропустить.

Есть какой-либо способ сделать это?

Да, это возможно. В одном из моих плагинов, где мне нужно минимальное ядро ​​WordPress (DB без плагинов и тем), вот что я делаю:

 <?php define('SHORTINIT', true); // load minimal WordPress require_once PATH_TO_WORDPRESS . '/wp-load.php'; // WordPress loader // use $wpdb here, no plugins or themes were loaded 

Константа PATH_TO_WORDPRESS я составил; вам просто нужно указать это на правильный путь. Например, в плагинах это может выглядеть так:

 require_once dirname(__FILE__) . '/../../../wp-load.php'; // backwards 'plugin-dir/plugins/wp-content' 

Настройка SHORTINIT на true безусловно, немного помогает производительности.

Если WP_DEBUG отключен, время, затрачиваемое на загрузку WordPress, выглядит следующим образом:

  • Без SHORTINIT: ~ 0,045 секунды
  • С SHORTINIT: ~ 0,0015 секунды

Если это для вашего собственного сайта, где требуется производительность, возможно, вы можете немного увеличить его, включив OpCache (например, APC или PHP OpCache в последних версиях).

Но я считаю, что 2 строки кода выше определяют SHORTINIT и требуют, чтобы wp-load.php – это то, что вы ищете.

Чтобы уточнить, этот файл является частью плагина, но он вызывается независимо от самого WordPress (через Ajax и напрямую). Он никогда не включается и не используется другими компонентами плагина или самого WP.

EDIT: Поскольку OP фактически связан с WP-API, а не с WordPress вообще, я добавляю это для решения актуального вопроса. Я оставлю исходный контент ответа, если он может помочь кому-то другому.

Я продолжал тестирование с помощью WP API и, как сказал @David в своем ответе, проблема, вероятно, что-то еще.

Я загрузил 12 плагинов в дополнение к остальным api, некоторые довольно «большие» плагины, а моя локальная установка содержит около 25 тем (один, конечно, конечно). Я отредактировал файл index.php WordPress и использовал microtime(true) для записи, когда все началось, а затем отредактировал один из контроллеров REST, чтобы рассчитать, сколько времени потребовалось от начала до получения конечной точки API.

Результат в моей системе постоянно составляет 0.04620.0513 секунд (без PHP OpCache и никакой другой загрузки системы). Таким образом, при загрузке WordPress мало влияет на производительность.

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

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

Загрузка php-файлов не так медленна, как чтение из вашего db, и это, вероятно, будет ваше время загрузки 500 мс. Вы должны на самом деле смотреть на снижение этого (параметры кэша wp и т. Д.), Но то, что я предлагаю вам по отношению к api, заключается в кэшировании вывода с использованием mu-plugin. Используя exit, мы можем загружать выходные данные из файла и обслуживать его мгновенно.

Наш метод: 1. Создайте папку с именем mu-plugins в папке wp-content (возможно, она уже существует)

  1. создайте файл api-cache.php

  2. введите этот код в свой файл:

     function get_api_cache(){ //dont run if we are calling to cache the file (see later in the code) if( isset($_GET['cachecall']) && $_GET['cachecall'] === true) return; $url = "$_SERVER[REQUEST_URI]"; //do a little error checking $uri= explode('/',$url); //we have a array (1st key is blank) if( $uri[1] !== 'wp-json' || $uri[2] !== 'wp' || $uri[3] !== 'v2'){ return; } //lock down the possible endpoints we dont want idiots playing with this... $allowed_endpoints= array( 'posts' ); $endpoint= array_pop($uri); // not sure if this is valid or not, is there more structure to some api calls? if( !in_array( $endpoint, $allowed_endpoints) ){ return; } //ok reasonably confident its a api call... $cache_folder= get_stylesheet_directory().'/api_cache/'; // prob best if not within php server but to get you going if(! file_exists ( $cache_folder ) ){ mkdir($cache_folder); //warning 777!! } /* * Need to choose a method of control for your cached json files * you could clear out the folder on update post/ taxonomies etc * or cron clear out hourly/weekly whatever freq you want */ if( file_exists($cache_folder.$endpoint.'.json') ){ $json= file_get_contents($cache_folder.$endpoint.'.json'); header('Content-Type: application/json'); echo $json; exit;// we need nothing else from php exit } else { //make sure there will be no errors etc.. $ch = curl_init(); $url= "http://$_SERVER[HTTP_HOST]$_SERVER[REQUEST_URI]?cachecall=true"; $timeout= 5; curl_setopt($ch, CURLOPT_URL, $url); curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, $timeout); $json = curl_exec($ch); curl_close($ch); file_put_contents($cache_folder.$endpoint.'.json', $json); } } get_api_cache(); 

Теперь вы должны заметить существенную разницу в времени загрузки на втором загрузке (это первый раз, когда он кэширует выход).

Несколько отказов:

  1. вы должны прочитать комментарии в коде
  2. Вам нужно закручиваться
  3. Вы должны знать, что папка с кешем – 777, я настоятельно рекомендую вам отодвинуть ее от своей папки темы и, желательно, за пределами ваших доступных http файлов.
  4. Не удалось поймать все крючки для захвата данных, которые нужно кэшировать, поэтому я использовал завиток для захвата содержимого, это может измениться в будущем, и hook / filter немного улучшит время процесса при создании файла кеша.
  5. Я не включил метод обновления файлов кеша. Вам нужно решить, как часто вы хотите обновлять сайт, который получает много сообщений в день и много посещений, вы можете выполнить задание cron, чтобы просто удалять файлы (например, 3 раза в день, ежечасно, каждые 10 минут , и т. д. – что является разумным компромиссом во время обновления?) или добавьте крючок, чтобы сохранить сообщение, чтобы обновлять только при изменении ваших сообщений и т. д.
  6. добавьте конечные точки в массив для них (вы можете удалить оператор if, чтобы разрешить все конечные точки, но тогда у вас может быть ситуация, когда 404s кэшируются!)

Вы должны попробовать это . Это плагин, который позволяет включать / отключать определенные плагины для пост-типов, страниц и других обстоятельств.

Для части темы, если вы ее написали, было бы легко добавить что-то в функцию.php, чтобы предотвратить присоединение каких-либо крючков или фильтров в случае запроса API.

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

Извините за мой бедный английский, если это вам полезно.

Поместите папку плагина в корневую программу WordPress.

 /public_html/my-plugin/my-plugin.php and include wordpress main file. require dirname( dirname( __FILE__ ) ).'/wp-load.php'; 

Или непосредственно в папке плагина

 /public_html/wp-content/plugins/my-plugin/my-plugin.php require_once dirname(__FILE__) . '/../../../wp-load.php'; 

Перед проверкой файл wp-load.php включен правильно и работает.

Файл wp-settings.php загружает все ядро, плагины и файлы тем. wordpress загружает первые файлы mu-plugins (wp-content / mu-plugins /) и предоставляет после действия hook muplugins_loaded . Запустите это действие, чтобы выгрузить все остальные загруженные файлы. Вы также можете найти, какой action hook предоставляет до muplugins_loaded и останавливать другие файлы и выполнение скриптов.

если определить константу SHORTINIT до включения wp-load.php, она включает в себя некоторые файлы, обеспечивающие DB, плагин или базовые функции. Когда мы хотим больше загружать файлы ядра, а не просто загружать плагины и файлы тем, то нашли решение.

 // file my-plugin.php //call before include file wp-load.php global $wp_filter; $wp_filter = array( // pass wp hook where to want exit extra wp loaded 'muplugins_loaded' => array( // prority 1 => array( // callback function register 'wp_extra_loaded_exit' => array( 'function' => 'wp_extra_loaded_exit', 'accepted_args' => 1 ) ) ) ); function wp_extra_loaded_exit(){ exit; } require dirname( dirname( __FILE__ ) ).'/wp-load.php'; // plugin code here. 

Мы проверяем, что muplugins_loaded hook определяет wordpress раньше, вы также можете определить, какой крючок определяется перед muplugins_loaded, а затем остановить эту точку после загрузки большего количества файлов WordPress. –

Если вы хотите протестировать свой скрипт, откройте файл wp-settings.php и найдите строку muplugins_loaded, затем выполните проверку echo.

 echo "Wordpress loaded in this point before"; do_action( 'muplugins_loaded' ); echo "After this wordpress not loading"; // Output fail bcz we exit