☰
WORDPRESS / PRACTICE

Оптимизация ответов WordPress REST API: как не передавать лишние данные

Оптимизация ответов WordPress REST API: как не передавать лишние данные

WordPress REST API по умолчанию может возвращать значительно больше данных, чем требуется фронтенду: полное содержимое записи, анонс, метаданные, ссылки, автора и другие служебные поля. Для одной записи это не всегда критично, но при загрузке коллекции лишние данные быстро увеличивают размер JSON-ответа и объем работы на сервере.

Оптимизация не требует изменений в WordPress Core. В большинстве случаев достаточно правильно формировать запросы: ограничивать количество записей с помощью per_page, выбирать нужные поля через _fields и не использовать _embed без реальной необходимости.

Почему лишние поля REST API создают проблему

Запрос к стандартному endpoint, например /wp-json/wp/v2/posts, возвращает объект записи со множеством свойств. Для карточки в списке новостей фронтенду часто нужны только идентификатор, заголовок, дата, slug и ссылка. Полные content или excerpt в таком сценарии не используются, но всё равно попадают в ответ.

Чем больше записей возвращает один запрос, тем объемнее становится JSON. Браузеру необходимо загрузить и разобрать эти данные, а PHP — подготовить ответ. Дополнительные затраты особенно заметны на сайтах с большими текстами, сложными метаданными или медленным сервером.

Это не означает, что каждый ответ по умолчанию критически медленный. Проблема возникает, когда большой объем данных регулярно передается для списков, поиска, мобильных клиентов или headless WordPress-проектов.

  • увеличиваются размер ответа и время его передачи;
  • фронтенд обрабатывает данные, которые не использует;
  • возрастает нагрузка на PHP и промежуточные кеши;
  • мобильные пользователи расходуют больше трафика.

Ограничивайте набор полей с помощью _fields

Параметр _fields позволяет попросить REST API вернуть только необходимые свойства. Это самый простой шаг для оптимизации стандартных endpoint’ов. Поля указываются через запятую без пробелов.

Например, для списка записей, где нужны только базовые данные, достаточно такого запроса:

/wp-json/wp/v2/posts?per_page=10&_fields=id,slug,date,title,link

Как выбирать поля для вложенных объектов

Некоторые свойства REST API являются объектами. Например, title обычно содержит отдельное поле rendered. Если фронтенду нужен только текст заголовка, можно указать вложенное поле, а не весь объект:

  • id — идентификатор записи;
  • slug — часть URL;
  • date — дата публикации;
  • title.rendered — отображаемый заголовок;
  • link — готовая ссылка на запись.
/wp-json/wp/v2/posts?per_page=10&_fields=id,slug,date,title.rendered,link

Не указывайте поля наугад

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

Также важно помнить, что _fields сокращает результат для клиента, но не превращает REST API в полностью кастомный SQL-запрос. WordPress по-прежнему подготавливает ответ в соответствии с логикой endpoint’а. Поэтому фильтрацию полей следует сочетать с разумным количеством элементов в запросе.

Используйте per_page и короткую пагинацию

Для коллекций не стоит загружать все записи одним запросом. Параметр per_page задает количество элементов на странице, а page — номер страницы. Короткие страницы уменьшают объем ответа и позволяют фронтенду показывать контент постепенно.

Практичный вариант для списка — запрос на 10 или другое количество записей, которое интерфейс действительно может одновременно показать:

  • используйте per_page в соответствии с размером списка на экране;
  • передавайте page для получения следующих порций данных;
  • не увеличивайте per_page только ради сокращения количества HTTP-запросов;
  • обрабатывайте ситуацию, когда страница выходит за пределы доступных записей.
/wp-json/wp/v2/posts?per_page=10&page=2&_fields=id,slug,date,title.rendered,link

Как определить количество страниц

В ответах коллекций WordPress обычно передает заголовки с информацией об общем количестве записей и страниц. Фронтенд может использовать их для кнопки «Показать еще», классической пагинации или бесконечной прокрутки.

Не ориентируйтесь только на количество элементов в текущем ответе: последняя страница может содержать меньше записей, чем указано в per_page. Проверяйте статус ответа и корректно обрабатывайте ошибки доступа или некорректный номер страницы.

Не добавляйте _embed без необходимости

Параметр _embed используется для включения в ответ связанных ресурсов: автора, featured image, терминов таксономий и других объектов, которые WordPress может получить для записи. Это удобно, когда фронтенду действительно нужны такие данные в одном запросе, но для списков параметр может заметно увеличить ответ.

Если карточка показывает только заголовок, дату и ссылку, _embed не нужен. Его добавление «на всякий случай» часто приводит к передаче вложенных объектов, которые никто не использует.

  • не используйте _embed автоматически в каждом запросе;
  • добавляйте его только для сценариев со связанными ресурсами;
  • вместе с _embed проверяйте, можно ли ограничить поля с помощью _fields;
  • сравнивайте размер ответа с _embed и без него.
/wp-json/wp/v2/posts?per_page=10&_embed&_fields=id,slug,title.rendered,_embedded

Когда _embed оправдан

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

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

Формируйте минимальный ответ в кастомных endpoint’ах

Если вы создаете собственный REST endpoint, не возвращайте весь объект WP_Post или необработанный результат запроса. Клиенту лучше передавать стабильную структуру с полями, которые нужны именно для этого сценария.

Например, endpoint для каталога может возвращать id, название, цену, короткий URL и изображение, но не полный контент, служебные метаданные и все связи объекта. Такой подход упрощает контракт между бэкендом и фронтендом и снижает риск случайного раскрытия внутренних данных.

  • определите DTO-подобную структуру ответа для каждого сценария;
  • не передавайте внутренние метаполя без необходимости;
  • нормализуйте даты, URL и названия полей в понятный формат;
  • документируйте обязательные и необязательные свойства.
register_rest_route('site/v1', '/cards', [
    'methods'  => 'GET',
    'callback' => function ($request) {
        $posts = get_posts([
            'post_type'      => 'post',
            'posts_per_page' => 10,
            'post_status'    => 'publish',
        ]);

        return array_map(function ($post) {
            return [
                'id'    => $post->ID,
                'slug'  => $post->post_name,
                'title' => get_the_title($post),
                'link'  => get_permalink($post),
            ];
        }, $posts);
    },
]);

Безопасность кастомных ответов

Минимизация JSON не заменяет проверку разрешений. Для приватных данных или endpoint’ов, доступных только авторизованным пользователям, отдельно настройте permission_callback и проверку прав. Не следует считать поле безопасным только потому, что оно не отображается в обычном интерфейсе.

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

Как проверить результат оптимизации

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

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

  • размер ответа в Network в браузере;
  • время ожидания и время загрузки JSON;
  • количество элементов и корректность пагинации;
  • наличие всех полей, которые читает JavaScript;
  • работу кеширования и повторных запросов;
  • логи PHP и ошибки REST API после изменений.
curl -i 'https://example.com/wp-json/wp/v2/posts?per_page=10&_fields=id,slug,date,title.rendered,link'

Распространенные ошибки

Одна из типичных ошибок — оставить _embed во всех запросах, даже если он нужен только на странице деталей. Другая — установить слишком большой per_page, чтобы «сократить» количество запросов. В результате один запрос становится тяжелым для сервера и браузера.

Также не стоит добавлять _fields, не проверив вложенные структуры. Запрос может формально вернуть ответ 200, но фронтенд будет ожидать title.rendered, а получит другую форму данных или вообще не получит нужное поле.

Частые вопросы

Нужно ли всегда использовать _fields в WordPress REST API?

Для больших коллекций и публичных запросов это желательная практика, особенно когда фронтенду нужна только часть объекта. Для внутреннего одноразового запроса польза может быть меньше, но структуру ответа всё равно стоит контролировать.

Заменяет ли _fields параметр _embed?

Нет. _fields ограничивает поля ответа, а _embed добавляет связанные ресурсы. Их можно использовать вместе, если фронтенду нужны встроенные данные, но следует проверить, какие именно свойства возвращаются и не стал ли JSON слишком большим.

Какое значение per_page выбрать?

Универсального значения нет. Ориентируйтесь на количество элементов, которое интерфейс показывает за один раз, размер записей и возможности сервера. Лучше использовать несколько умеренных страниц, чем один чрезмерно большой запрос.

Снижает ли _fields нагрузку на PHP?

Он гарантированно сокращает объем данных, формируемых для отправки клиенту, но не всегда устраняет всю внутреннюю работу WordPress по подготовке объекта. Для максимального эффекта сочетайте _fields с пагинацией, отказом от ненужного _embed и минимальными кастомными ответами.

Вывод

Оптимальный REST-запрос WordPress должен возвращать не «все доступное», а только данные для конкретного экрана или функции. Начните с трех шагов: ограничьте per_page, перечислите нужные поля через _fields и уберите _embed там, где нет связанных ресурсов.

Для собственных endpoint’ов формируйте минимальную структуру ответа и проверяйте ее в браузере, через curl и на тестовых сценариях. Это уменьшает JSON, ускоряет работу фронтенда и помогает не создавать лишнюю нагрузку на PHP без опасных изменений в ядре WordPress.

← Все материалы WordPress