🥊 Gato GraphQL vs WPGraphQL: бой!
Обновление 01.05.2024: Ознакомьтесь со сравнением Gato GraphQL vs WPGraphQL.
Дамыыыыыыыыыыы и господа.

Добро пожаловать на арену MGM Grand Garden Arena — место проведения боя века! Сегодня вечером мы творим историю. Два молодых бойца встретятся лицом к лицу на ринге, сражаясь за приз, ради которого они так усердно трудились:
Стать чемпионом мира «GraphQL в WordPress» 🏆
Справа от нас — действующий чемпион. Несмотря на то что ему всего 4 года, он уже полон опыта: недавно достиг версии 1.0 и был опубликован в директории wp.org, и он очень популярен в народе.
🥁 Встречайте 🥁 аплодисментами 🥁 ...... WPGraphQL!

Слева от нас — претендент. Он пробыл в мире лишь 1 месяц, но полон энергии и амбиций, демонстрируя свою силу с первого дня. Именно он искал сегодняшней встречи. Сегодня вечером — его шанс, и весь мир смотрит.
🥁 Встречайте 🥁 аплодисментами 🥁 ...... Gato GraphQL!

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

Кто победит? Удержит ли WPGraphQL своё преимущество, опираясь на поддержку своих сторонников? Или же новичок Gato GraphQL убедит ничего не подозревающее сообщество в мощи своих кулаков, оставив за собой след восхищения, который перетянет толпу на его сторону?
Сегодня вечером, дамы и господа, мы это узнаем.
Делайте ставки. И наслаждайтесь матчем!
🤣🤣🤣🤣🤣🤣🤣🤣🤣🤣🤣🤣🤣🤣🤣🤣🤣🤣
Недавно меня попросили объяснить различия между моим плагином, Gato GraphQL, и WPGraphQL.
Оба плагина являются GraphQL-серверами для WordPress, то есть служат одной цели. Однако под капотом у них разные характеристики, из-за которых один может оказаться лучше другого для удовлетворения тех или иных требований.
Несмотря на то что я предвзят в пользу своего плагина, я постарался провести честное сравнение, основанное на темах, которые считаю важными как для GraphQL, так и для WordPress. (Если читатели хотят сравнения по другой теме, я готов его сделать.)
Сравнение не является исчерпывающим. Например, я также хотел бы провести бенчмаркинг, измерив скорость обработки одного и того же GraphQL-запроса на обоих серверах. (Если читателям это предложение покажется привлекательным, я могу сделать это в следующей статье.)
Я разделил сравнение на 4 основные области: Популярность, Стиль кода и стандарты, Насущные вопросы и Расширение охвата — по 3 пункта в каждой, что даёт в общей сложности 12 «раундов». В конце судьи выносят свой вердикт и называют чемпиона.
Нажмите ниже, чтобы сразу перейти к нужной теме:
🔔 Дин 🔔 дин 🔔 диииинь...
Стартовый гонг прозвучал...
Матч начался!
Популярность
Любое программное обеспечение (или технология, если на то пошло) должно использоваться людьми, иначе его превосходство над альтернативами останется лишь анекдотом.
Например, несмотря на то что существуют альтернативы, позволяющие печатать быстрее, мы по-прежнему в основном используем клавиатуру QWERTY.
Насколько популярны два плагина?
Раунд 1: Кто использует и насколько завершён
WPGraphQL до сих пор был синонимом GraphQL в WordPress. За более чем 4 года разработки (начиная с ноября 2016 года) он собрал более 2,8 тыс. звёзд на репозитории, сообщество более 4600 подписчиков и почти 100 участников проекта.
Он достиг версии 1.0 и был загружен в директорию плагинов на wp.org в ноябре 2020 года. С тех пор набрал более 8000 активных установок. В настоящее время это единственное решение для получения контента WordPress в Gatsby и, совсем недавно, несколько проектов добавили его в свои стеки, включая Headless-фреймворк WPEngine и стартер WordPress для Next.js от WebDevStudios.
Иными словами, WPGraphQL популярен.
Разработка Gato GraphQL всерьёз началась около 1,5 лет назад (в рамках более широкого проекта) и достигла «достаточно хорошего» состояния 6 месяцев назад, собрав с тех пор 150 звёзд на репозитории. Плагин сейчас на версии 0.7, и до версии 1.0 ещё несколько месяцев (например, в схеме пока нет категорий).
В прошлом месяце я запустил этот сайт gatographql.com и с тех пор продвигаю плагин через блог (как статья, которую вы сейчас читаете), а также опубликовал вводную статью на CSS-Tricks. Эти усилия привлекли на сайт несколько сотен человек, и более 100 посетителей скачали плагин.
Иными словами, Gato GraphQL медленно, но уверенно набирает популярность и является работой в процессе.
Победитель раунда: WPGraphQL.

Раунд 2: Наличие расширений
Расширения позволяют взаимодействовать с другими плагинами через Gato GraphQL.
WPGraphQL имеет расширения для ACF, WooCommerce, Yoast и ряда других.
У Gato GraphQL пока нет расширений, и я не жду, что их будет много до выхода версии 1.0.
Тем не менее архитектура Gato GraphQL уделяет расширениям большое внимание, позволяя пользователю управлять ими (включать, отключать, настраивать и читать их документацию) из единого места — страницы «Modules»:

Иными словами, пока у WPGraphQL расширения уже есть, Gato GraphQL готовит для них почву.
Победитель раунда: WPGraphQL.

Раунд 3: Целевая аудитория
WPGraphQL ориентирован на разработчиков: если вы хотите извлечь данные из своего WordPress-сайта, вам нужно сохранить GraphQL-запрос где-то в коде (скорее всего, в какой-нибудь JavaScript-функции). Чтобы его использовать, нужно достаточно хорошо разбираться в программировании.
Gato GraphQL, напротив, следует философии WordPress, согласно которой им должен уметь пользоваться каждый, включая нетехнических специалистов. Для достижения этой цели он позволяет создавать GraphQL-запросы и управлять ими через редактор WordPress, так что открытие данных сайта через API становится таким же простым, как написание записи в блоге.
Кроме того, Gato GraphQL уделяет особое внимание предоставлению клиентов для визуального взаимодействия с GraphQL-сервисом. Оба плагина предоставляют клиент GraphiQL для выполнения запросов, однако только Gato GraphQL также предоставляет клиент Voyager для интерактивного исследования схемы:

Победитель раунда: Gato GraphQL.

Стиль кода и стандарты
Поговорим о коде!
Если вы используете GraphQL, скорее всего, вы делаете headless WordPress и рендерите сайт с помощью какого-либо JavaScript-фреймворка — это современная парадигма. Более того, WordPress может быть старой CMS, но GraphQL — современный интерфейс для доступа к данным сайта. Поэтому я могу с уверенностью предположить, что вы опытный разработчик, стремящийся к элегантному коду, и не согласитесь использовать неоптимальное решение.
Насколько элегантен код (как в их собственных кодовых базах, так и в ожидаемых от нас пользовательских реализациях) у этих двух плагинов?
Раунд 4: Требования к PHP
И WPGraphQL, и Gato GraphQL требуют PHP 7.1+.
Однако есть разница: Gato GraphQL фактически написан с использованием PHP 7.4, а затем транспилируется до PHP 7.1 для продакшена.
Таким образом, разработка Gato GraphQL значительно приятнее: можно использовать новые возможности PHP, включая тип object, типизированные свойства и стрелочные функции. А когда будет добавлена поддержка PHP 8.0 (что произойдёт при выходе новой версии Lando), станут доступны union types, выражение match и другие возможности.
Победитель раунда: Gato GraphQL.

Раунд 5: Практики кодирования
Начнём с WPGraphQL. Заглянув в репозиторий wp-graphql/wp-graphql, я сразу обращаю внимание на одну вещь:

При увеличении:

Извините, но у меня есть только одна реакция на это:

Коммитить папку vendor Composer в репозиторий — это плохая практика, и Composer прямо это не рекомендует.
Исправить эту проблему несложно (я даже описал способ на основе GitHub Actions), поэтому мне интересно, почему это так.
Осмелюсь сказать, что в этом раунде WPGraphQL бьёт сам себя!

Продолжим. Разработка для WPGraphQL требует знания огромного количества хуков (actions и filters). Зайдя в Developer reference WPGraphQL, можно оценить их масштаб.
Чтобы сделать скриншот списка actions, мне пришлось уменьшить масштаб браузера до 50%:

Для списка filters пришлось уменьшить до 30% (минимум, поддерживаемый Firefox), и даже тогда не удалось получить весь список:

Перейдём к репозиторию GatoGraphQL/GatoGraphQL — монорепозиторию, содержащему Gato GraphQL (среди других проектов).
Вот некоторые характеристики кода:
✅ Соответствует стандартам PSR-1, PSR-4 и PSR-12.
✅ Весь код разбит на множество атомарных пакетов, и все они (более 100 для плагина, более 200 для всего проекта) размещены в одном монорепозитории.
✅ Использует Composer для управления всеми зависимостями.
✅ Использует Symfony Dependency Injection для управления всеми сервисами приложения. Чтобы зарегистрировать новый type resolver, field resolver или directive resolver, достаточно зарегистрировать новый сервис в контейнере.
✅ Каждый класс является сервисом, и Symfony Dependency Injection обеспечивает автовайринг всего приложения.
✅ Базовый GraphQL-сервер не зависит от CMS. Gato GraphQL реализует контракты для WordPress и добавляет немного пользовательской логики (например, для предоставления клиентов).
Код, специфичный для WordPress, составляет лишь около 10% от общего объёма. Воспроизведение этих 10% для другого фреймворка или CMS (Laravel/Drupal и т.д.) позволит создать для них реализацию GraphQL-сервера.
✅ Как следствие независимости от CMS, написание резолвера подразумевает кодирование его общей бизнес-логики, основанной на переиспользуемых сервисах. Мы никогда не думаем в категориях кода WordPress и редко сталкиваемся с его техническим долгом.
✅ Аналогично, GraphQL-схема не является точной копией модели данных WordPress, обходя технический долг, накопленный WordPress на уровне данных, и предоставляя чистый интерфейс.
✅ Проблема N+1 в GraphQL не может возникнуть, по архитектурному замыслу, и не беспокоя разработчика.
✅ Сервер является не только GraphQL-сервером: это API-сервер, где ответ может быть представлен в других форматах или спецификациях (например, REST) из единого источника истины. (Подробнее об этом в раунде 11.)
✅ Каталог vendor не коммитится. Вместо этого исходный код преобразуется в дистрибутивный код (то есть финальный плагин для установки на WordPress-сайт) через GitHub Actions и публикуется в репозитории dist, где папка vendor уже присутствует.
✅ При генерации кода для дистрибуции он скопирован с помощью PHP-Scoper, а исходный код, написанный на PHP 7.4, транспилируется до PHP 7.1.
✅ Поскольку проблема скопирования решена, плагин может использовать любую стороннюю зависимость. В настоящее время используются DependencyInjection, Cache и Dotenv от Symfony, Guzzle (для взаимодействия с внешними API), Pipeline от The League и многие другие.
Это важно не только для настоящего, но и для будущего: я могу быть уверен, что смогу использовать любую зависимость из репозитория Packagist, и мне не нужно изобретать велосипед.
✅ Поля подписаны на типы, что делает GraphQL-схему лёгкой для расширения.
Победитель раунда: Gato GraphQL (с большим отрывом, осмелюсь сказать, если вы не против).

Раунд 6: Расширение схемы
Давайте добавим поле в GraphQL-схему.
Следуем туториалу для WPGraphQL. Предлагаемый код приведён ниже. Он объявляет action-хук для выполнения функции, которая объявляет массив. Как описание полей, так и их разрешение предоставляются внутри массива:
add_action( 'graphql_register_types', function() {
register_graphql_field( 'RootQuery', 'myNewField', [
'type' => 'String',
'args' => [
'myArg' => [
'type' => 'String',
'description' => __( 'Description for how the argument will impact the field resolver', 'your-textdomain' ),
],
],
'resolve' => function( $source, $args, $context, $info ) {
if ( isset( $args['myArg'] ) ) {
return 'The value of myArg is: ' . $args['myArg'];
}
return 'test';
},
]);
});Этот пример максимально прост: резолвер по сути ничего не делает. И всё же мне уже трудно смотреть на этот код и сразу понять, что он делает. Нет, я не иронизирую: все цвета этого кода в моём редакторе борются за моё внимание. Кроме того, нет разделения ответственности, и код не выглядит особо переиспользуемым.
Следовательно, именно разработчику (то есть вам) придётся сделать код читаемым, переиспользуемым, без багов и многим другим в процессе разработки приложения; сама библиотека, похоже, мало помогает в этом.
Я называю этот стиль «ADD»: Array-Driven Development. Не могу сказать, что являюсь его поклонником.
(Справедливости ради по отношению к WPGraphQL: это стандартная практика кодирования, и именно её использует базовый движок webonyx/graphql-php.)
В Gato GraphQL весь код соответствует SOLID. Чтобы зарегистрировать поле в GraphQL-схеме, мы создаём класс, реализующий интерфейс FieldResolverInterface (точнее, расширяющий AbstractSchemaFieldResolver, в котором многие методы уже реализованы), и регистрируем его в контейнере.
Например, этот код предоставляет поля username, email и url для типа User:
class UserFieldResolver extends AbstractSchemaFieldResolver
{
public static function getClassesToAttachTo(): array
{
return [
UserTypeResolver::class,
];
}
public static function getFieldNamesToResolve(): array
{
return [
'username',
'email',
'url',
];
}
public function getSchemaFieldDescription(TypeResolverInterface $typeResolver, string $fieldName): ?string
{
$descriptions = [
'username' => $this->translationAPI->__("User's username handle", "users"),
'email' => $this->translationAPI->__("User's email", "users"),
'url' => $this->translationAPI->__("URL of the user's profile in the website", "users"),
];
return $descriptions[$fieldName];
}
public function getSchemaFieldType(TypeResolverInterface $typeResolver, string $fieldName): ?string
{
$types = [
'username' => SchemaDefinition::TYPE_STRING,
'email' => SchemaDefinition::TYPE_EMAIL,
'url' => SchemaDefinition::TYPE_URL,
];
return $types[$fieldName];
}
public function resolveValue(TypeResolverInterface $typeResolver, object $user, string $fieldName, array $fieldArgs = [])
{
switch ($fieldName) {
case 'username':
return $this->usersAPI->getUserLogin($user);
case 'email':
return $this->usersAPI->getUserEmail($user);
case 'url':
return $this->usersAPI->getUserURL($user);
}
return null;
}
}Я действительно считаю, что моё решение элегантнее, чем у WPGraphQL. Однако это дело вкуса. Я знаю, что многие разработчики не против Array-Driven Development и даже предпочитают его, поскольку в компактном блоке кода можно реализовать всю логику.
Победитель раунда: ничья.

Антракт
Что за вечер у нас, дамы и господа.

Мы достигли середины боя, и сейчас самое время для перерыва и комментариев о том, что мы уже увидели.
(Тем временем мне следовало бы показать рекламу от моих спонсоров. К сожалению, их у меня пока нет. Если вы хотите, чтобы ваша компания финансировала разработку Gato GraphQL и получила рекламу на таком первоклассном мероприятии, напишите мне.)

Что за матч у нас! WPGraphQL поначалу был весь огонь и ярость! Он начал бой в отличной форме, нанося Gato GraphQL страшные мощные удары, который едва держался на ногах. Удар за ударом за ударом. Я бы не хотел оказаться на месте Gato GraphQL.
Должен признать, после первых 2 раундов я думал, что матч скоро закончится. Я ждал нокдауна в любой момент. Ожидал увидеть трепещущее полотенце с мольбой о пощаде. Но Gato GraphQL выстоял. Это надо признать. Какая несокрушимая решимость — это поистине замечательно!
И тогда произошло преображение. Где-то в начале 3-го раунда Gato GraphQL словно обрёл силы ниоткуда и начал не только защищаться, но и наносить ответные удары, многие из которых достигли лица WPGraphQL. Я видел, как WPGraphQL дрожал и шатался! Мы никогда не видели ничего подобного от нашего действующего чемпиона мира. Какое поистине замечательное преображение мы только что наблюдали!
И затем, поколебав уверенность соперника, начиная с 4-го раунда Gato GraphQL взял на себя инициативу и нанёс серию смертоносных ударов. Это было ошеломительно! К счастью, перед ним стоит наш чемпион мира WPGraphQL, который выдержал удары, воодушевлённый криками и сочувствием толпы. Что за герой! Любой другой рухнул бы на месте, но только не он — он вынес удары как настоящий чемпион.
Но останется ли он чемпионом надолго? Никто ещё не был нокаутирован, никто не бросил полотенце. Бой может в любой момент принять решающий поворот. Оба бойца знают, чего хотят, и я уверен, что они выйдут снова со всей своей мощью и решимостью, чтобы обрушиться на соперника и победить.
Что за матч у нас!
А теперь, дамы и господа, два воина возвращаются на ринг.

Продолжаем бой!
Насущные вопросы
GraphQL-серверу необходимо учитывать множество аспектов, чтобы удовлетворить тезис «получи нужные данные, не больше и не меньше».
Например:
- Насколько он безопасен? Как убедиться, что мы не раскрываем приватные данные через публичный эндпоинт?
- Насколько он производителен? Как снизить нагрузку на сервер при многократной отправке одного и того же запроса, сделав его при этом максимально быстрым?
- Насколько он прост? Насколько хорошо он интегрирован с WordPress, чтобы использовать возможности CMS?
И многие другие вопросы. Это лишь небольшая выборка, которую я сделал и рассмотрю в следующих 3 раундах.
Раунд 7: Persisted queries
Persisted queries объединяют лучшее из GraphQL и REST: они создаются с помощью GraphQL, поэтому нет избыточной или недостаточной выборки данных, но публикуются на сервере как эндпоинт с собственным URL.
Persisted queries предоставляют следующие преимущества:
✅ Безопасность: вместо предоставления доступа к любым данным через единый эндпоинт можно заранее определить, какие данные раскрывать.
✅ Скорость: будучи доступны по собственному URL, они могут кэшироваться на каждом уровне между клиентом и бэкендами (на сервере, CDN, в браузере) с помощью стандартного HTTP-кэширования.
WPGraphQL предлагает поддержку persisted queries через два расширения:
Кроме того, Джейсон Баль (создатель WPGraphQL) недавно объявил, что в ближайшем будущем добавит поддержку persisted queries в WPGraphQL.
Мне интересно, что он имеет в виду, ведь два расширения уже существуют. Чем это будет отличаться от них? Возможно, он хочет встроить это в ядро плагина, чтобы усилить общие меры безопасности без зависимости от третьих сторон?
Или, может быть, он увидел реализацию в Gato GraphQL и хочет предоставить аналогичный опыт, управляя им через визуальный редактор вместо чистого кода?
Что приводит нас к Gato GraphQL. Он не только предлагает persisted queries, но и стремится сделать их центральной частью предложения:
✅ Плагин позволяет отключить единый эндпоинт, и пользователям рекомендуется раскрывать данные только через persisted queries.
(В отличие от этого, WPGraphQL по умолчанию отключает лишь интроспекцию, но не сам эндпоинт. Иными словами, злоумышленники всё равно могут получить доступ к приватным данным; им просто усложняют задачу, скрывая сведения о том, какие данные существуют.)
✅ Он глубоко интегрирован с редактором WordPress, поэтому создание persisted query требует столько же усилий, сколько создание записи в блоге, и с этим справится любой, а не только программисты.
✅ Persisted queries не статичны: они могут использовать переменные GraphQL, значения которых передаются через URL-параметры при вызове эндпоинта.
Ознакомьтесь с процессом создания и выполнения persisted query в моём плагине:
Победитель раунда: Gato GraphQL.
Раунд 8: Кэширование
У GraphQL есть серьёзная проблема: его сложно кэшировать. Причина в том, что он зависит от отправки POST-операций на единый эндпоинт. Поскольку единый эндпоинт выдаёт разные результаты, а запрос передаётся в теле запроса, а не в URL-параметрах, единый эндпоинт не может быть закэширован.
Стандартное решение, предлагаемое многими GraphQL-серверами, — перенести кэширование на клиент и использовать идентификаторы объектов как ключи кэша вместо URL эндпоинта. Самая популярная библиотека, обеспечивающая эту функциональность, — клиент Apollo.
В репозитории WPGraphQL есть обсуждение всех доступных вариантов кэширования для WPGraphQL. Примечательно, что большинство из них — внешние инструменты (например, клиент Apollo или WordPress Object Cache), что означает добавление дополнительного слоя в приложение, увеличение его сложности и, возможно, снижение производительности.
(Эти причины, по всей видимости, отчасти стоят за решением реализовать persisted queries непосредственно в WPGraphQL.)
Например, клиент Apollo работает, ну, на клиенте. При доступе к сайту со слабого мобильного телефона этот дополнительный JavaScript-код негативно скажется на производительности приложения.
Аналогично, разработчики, работающие с WordPress, могут хорошо знать PHP, но не так хорошо — JavaScript. Теперь кэширование их API потребует от них также думать о JavaScript-слое.
Gato GraphQL подошёл к этой теме умнее. Поскольку он предоставляет persisted queries, то есть запросы выполняются по собственному эндпоинту, он позволяет кэшировать URL этих эндпоинтов через HTTP-кэширование.
Заголовок HTTP-кэширования содержит значение max-age, автоматически рассчитанное из значений max-age для всех полей запроса, и эта информация настраивается в редакторе WordPress для каждого поля отдельно.
Как следствие, API может кэшироваться на нескольких уровнях (клиент, CDN, сервер) и управляется нативно внутри плагина, без необходимости добавлять ещё один слой.
Посмотрите это видео, демонстрирующее кэширование API-эндпоинтов:
Победитель раунда: Gato GraphQL.
Раунд 9: Интеграция с Gutenberg
Раньше Gutenberg считался будущим WordPress. Больше нет: Gutenberg теперь настоящее WordPress (поэтому мы можем называть его редактором WordPress), а Full Site Editing стал новым будущим.
Само собой разумеется, что наши API должны хорошо интегрироваться с редактором WordPress. Это означает не только получение и публикацию данных для блоков, но и потенциальное обеспечение функций самого редактора WordPress.
Например, поскольку GraphQL-подписки позволяют серверу отправлять данные клиенту в реальном времени, это было бы уместно для функций совместного редактирования и уведомлений.
WPGraphQL может запрашивать данные блоков через расширение WPGraphQL Gutenberg. Это расширение создаёт новый тип для каждого блока, поэтому у нас есть CoreParagraphBlock, CoreQuoteBlock и т.д.
Gato GraphQL вскоре также сможет запрашивать данные блоков (работа в процессе). Однако вместо создания нового типа для каждого блока будет использоваться единый тип Block для представления всех блоков, а затем можно будет извлекать конкретные метаданные блока по его названию.
Например, посмотрите, как можно переводить содержимое внутри блока-абзаца (используя директиву @strTranslate, которая подключается к API Google Translate):
query TranslateStringsInBlocks {
post(by: { id: 1657 }) {
title
paragraphBlocks: blockDataItems(
filterBy: { include: "core/paragraph" }
)
translatedParagraphBlocks: blockDataItems(
filterBy: { include: "core/paragraph" }
)
@underJSONObjectProperty(by: { path: "attributes.content" })
@underEachArrayItem
@strTranslate(from: "en", to: "fr")
}
}Победитель раунда: ничья.
Расширение охвата
«У меня есть мечта.»
Блоки Gutenberg были задуманы как единый интерфейс для создания контента в WordPress, значительно упрощающий разработку кода для CMS и обучение пользователей.
Введённые для создания контента, блоки неуклонно завоёвывают все остальные области CMS, включая виджеты, меню и, в ближайшем будущем, темы через Full Site Editing. А в будущем они также будут поддерживать многоязычные возможности и совместное редактирование (функции, о которых мы, возможно, даже не думаем в контексте блоков), и кто знает, что ещё.
Мы можем думать о GraphQL в тех же категориях: как о едином интерфейсе для взаимодействия с данными. Это означает не только получение и отправку данных, но и любое взаимодействие с данными, включая редактирование.
WordPress имеет уникальный шанс стать настоящей ОС веба: система, работающая на Gutenberg, которая позволяет пользователю вводить любой тип контента (текст, изображения, видео, аудио и т.д.), обрабатывать его с помощью собственных инструментов или какого-либо облачного сервиса и публиковать в конечное место назначения — будь то WordPress-сайт или где-то ещё.
Но за этой мощной мечтой должен стоять по-настоящему мощный API, способный удовлетворить любые требования. API, который может быть основан на GraphQL, но который разработан для того, чтобы также выходить за его рамки.
Раунд 10: Поддержка пользовательских директив

WPGraphQL не поставляется ни с одной директивой. Я не говорю, что он их не поддерживает (его движок webonyx/graphql-php поддерживает), но он не предлагает реализации ни одной пользовательской директивы.
«Ну и что?» — возможно, подумаете вы. «Зачем нам директивы? Если кому-то нужно изменить результат запроса, он может сделать это на своём клиенте!»

Это вопрос мнения, и здесь нет правильного или неправильного. Но позвольте сказать вам кое-что: директивы — невероятно полезная функция, которая помогает GraphQL выделиться на фоне REST. Если вы их не используете, скорее всего, вы не извлекаете максимум из своего API.
Директивы не регулируются спецификацией, поэтому GraphQL-серверы могут реализовывать их как угодно, делать их настолько мощными, насколько нужно. Именно поэтому многие новые функции в GraphQL сначала вводятся через директивы, например @stream и @defer.
Gato GraphQL относится к директивам с почтением. Они выполняются только один раз с данными всех сущностей, для всех полей, к которым применяются (что объясняет, почему директива @strTranslate может так быстро получать результаты от API Google Translate), а сам GraphQL-движок основан на конвейере директив.
Ах, но вы боитесь сделать всю эту мощь доступной для пользователей, не так ли? Это обоснованное опасение. Но тогда можно просто отключить доступ к единому эндпоинту и предоставлять доступ к данным только через persisted queries, где вы (администратор сайта) — единственный человек с доступом к директивам.
Так что либо вы получаете пользу, либо ничего не происходит.
Если вы любите директивы, отлично — вы полюбите Gato GraphQL! ❤️
Но, с другой стороны, если вам это не нравится, ничего не происходит.
Победитель раунда: Gato GraphQL.
(Если вы считаете, что «нам не нужны никакие директивы», пожалуйста, не злитесь на меня... Я просто делаю свою работу.)
Раунд 11: Поддержка REST
«Что? REST? Какой REST? Разве мы не говорим о GraphQL? Зачем вы говорите о REST? Зачем вы усложняете мою жизнь?»

Да, на первый взгляд эта тема выглядит неуместно. Но я включил её в это сравнение по очень простой причине: Мэтт Малленвег заявил, что рассматривает GraphQL для возможного включения в ядро WordPress, и главное, о чём будут беспокоиться контрибьюторы, — необходимость поддерживать две кодовые базы.
Что приводит к очевидному вопросу: может ли GraphQL-сервер также обрабатывать REST?
Ответ — «частично да» для WPGraphQL и «полностью да» для Gato GraphQL.
Относительно WPGraphQL. Можно определить REST-эндпоинт, который при вызове просто выполняет GraphQL-запрос с необходимыми полями — либо как внутренний вызов к GraphQL-движку, либо как внешнюю POST-операцию к тому же веб-серверу.
Но этого недостаточно для удовлетворения требований WP REST API, поскольку у него также есть JSON-схема, без которой не обойтись.
Относительно Gato GraphQL. Должен признать, мне повезло, потому что работа над его базовым движком (серверной компонентной моделью под названием PoP) началась примерно в 2013 году, то есть за несколько лет до того, как я узнал о GraphQL, и этот проект развивался с рядом собственных идей (которые я задокументировал в этой своей старой статье).
Затем, когда около 1,5 лет назад я начал программировать CMS-агностический GraphQL-сервер (на котором стоит Gato GraphQL), я объединил идеи, разработанные для PoP, с основами, заложенными GraphQL, создав систему, которая полностью поддерживает спецификацию GraphQL, будучи способной добавлять к ней иной набор возможностей.
В этом отношении схема, используемая PoP, является API-агностической и является надмножеством схемы GraphQL. Схема PoP находится по адресу /api/graphql/?query=fullSchema.
Затем слой GraphQL-сервера форматирует схему PoP в соответствии со спецификацией GraphQL, что создаёт GraphQL-схему. И аналогичным образом можно создать JSON-схему, необходимую для WP REST API.
Генерация этой JSON-схемы ещё не выполнена, но она осуществима.
Что уже сделано — так это выдача ответа на запрос в нескольких форматах. Например, этот GraphQL-запрос:
{
posts {
id
title
date
author {
name
}
}
}Также разрешается через этот REST-эндпоинт: /posts/api/rest/?query=id|title|date|author.name.
И на этом можно не останавливаться. Нужно выдать результаты в другом формате, например XML? Без проблем: /api/?query=posts.id|title|date|author.name&datastructure=xml.
(Это может помочь реализовать предложение по новому инструменту импорта/экспорта для WordPress, основанному на схеме. Это также делает немного более очевидным то, что я сказал ранее: единый интерфейс может обеспечивать все взаимодействия с данными — как внутри CMS, так и между CMS и внешними API.)
Победитель раунда: Gato GraphQL.
Раунд 12: Поддержка новых возможностей
Является ли спецификация GraphQL окончательной? Ответ — нет: спецификация постоянно развивается. Прямо сейчас открыто 100 issues, многие из которых содержат предложения, которые будут формализованы в будущем.
Среди этих 100 issues наверняка найдутся новые возможности, которыми мы можем воспользоваться уже сегодня, не правда ли? Если так, зачем ждать?
Именно так я думаю.

«Но если чего-то нет в спецификации GraphQL, то не следует добавлять это в GraphQL-сервер, иначе пользователи запутаются!»
Хороший аргумент. Однако если сделать новые возможности доступными только в режиме opt-in, пользователи будут обязательно о них осведомлены, и никаких проблем или недоразумений не возникнет.
Снова: именно так я думаю. Это, однако, дело мнения, поэтому если вы предпочитаете использовать только функции, которые есть в каждом GraphQL-сервере, — это нормально.
Я считаю, что именно так работает WPGraphQL. По крайней мере, я не видел ни одной функции, выходящей за рамки того, что одобрено в спецификации.
Для Gato GraphQL же я регулярно просматриваю список issues в спецификации и, если нахожу какую-то интересную функцию, которую мой сервер может поддержать без особых усилий, реализую её. (Это действительно одно из моих хобби.)
Вот «перспективные» функции, которые я реализовал к настоящему времени:
✅ Выполнение нескольких запросов
✅ Пространства имён схемы
✅ Вложенные мутации
✅ Компонуемые директивы
✅ Проактивная обратная связь
✅ Версионирование полей и директив
И я уже планирую добавить:
✳️ Subscriptions (это уже часть спецификации)
✳️ Директивы @stream и @defer
✳️ Синтаксис плоской цепочки
Победитель раунда: Gato GraphQL.
Вердикт!
Дамы, господа.

Что за незабываемый вечер! Что за матч мы только что пережили! Два тяжеловеса, отдавших всё ради своей мечты.
Мечты, которую преследуют оба, но поймать может лишь один.
И теперь мы узнаем, кто это. Настало время правды!
Кто станет чемпионом мира «GraphQL в WordPress»?
Будет ли это широко признанный, любимый народом, упоминаемый в крупных изданиях действующий чемпион — WPGraphQL?
Или это будет дерзкий, наступающий на ноги без извинений, приходящий незваным претендент — Gato GraphQL?

Мы ждём вердикта судьи. Какое напряжение! О господи, дай моему сердцу выдержать этот момент!
🥁 И 🥁 победитель 🥁 этоооооооооооооооооо 🥁 ...
Ничья!
2 бойца, 2 тяжеловеса — ничья!

Какой замечательный момент! Два претендента обнимают друг друга, показывая, что мы все друзья в сообществе WordPress, как одна большая семья.
Итак, каково обоснование ничьей? Судья объясняет:
👑 WPGraphQL более популярен, и его использование шире распространено.
👑 Gato GraphQL имеет лучшую архитектуру и в долгосрочной перспективе потенциально может лучше служить WordPress.
Дамы и господа, вы услышали вердикт судьи!
И наш трофей имеет две перчатки: по одной для каждого претендента.

Но каков ваш вердикт?
Продолжите ли вы безоговорочно использовать WPGraphQL для своих headless-задач?
Или дадите Gato GraphQL шанс, которого он добивается, скачаете плагин и попробуете его?
Дамы и господа. Это всё на эту ночь.
Мы искренне надеемся, что вам понравился матч.
И будем надеяться, что вскоре состоится новая встреча наших двух чемпионов.
Спокойной ночи.
Обновление 01.05.2024: Узнайте больше в сравнении Gato GraphQL vs WPGraphQL.