🥊 Gato GraphQL vs WPGraphQL: walka!
Aktualizacja 01/05/2024: Sprawdź porównanie Gato GraphQL vs WPGraphQL.
Paaaaaaaaaanie i panowie.

Witamy w MGM Grand Garden Arena na walce stulecia! Dziś wieczór tworzymy historię. Dwóch młodych zawodników stanie naprzeciw siebie na ringu, walcząc o nagrodę, na którą tak ciężko pracowali:
Zostać mistrzem świata "GraphQL w WordPress" 🏆
Po naszej prawej stronie mamy obecnego mistrza. Choć ma zaledwie 4 lata, jest już pełen doświadczenia — niedawno osiągnął wersję 1.0 i został opublikowany w katalogu wp.org, ciesząc się dużą popularnością wśród tłumów.
🥁 Przywitajcie 🥁 z 🥁 aplauzem 🥁 ...... WPGraphQL!

Po naszej lewej stronie mamy pretendenta. Jest na świecie od zaledwie 1 miesiąca, ale jest pełen energii i ambicji, demonstrując swoją siłę od pierwszego dnia. To on szukał dzisiejszego starcia. Dziś wieczór to jego szansa, a świat patrzy z uwagą.
🥁 Przywitajcie 🥁 z 🥁 aplauzem 🥁 ...... Gato GraphQL!

Dziś wieczór nasi zawodnicy spotkają się twarzą w twarz po raz pierwszy, w walce na 12 rund. Zajmując pozycje w centrum ringu w oczekiwaniu na dzwonek otwierający, badają się nawzajem, próbując znaleźć swoje słabe punkty. Jednak obaj prezentują wyłącznie pewność siebie.

Kto zwycięży? Czy WPGraphQL utrzyma swoją przewagę, opartą na wsparciu zwolenników? A może nowicjusz Gato GraphQL przekona niczego niepodejrzewającą społeczność o sile swoich pięści, pozostawiając za sobą falę podziwu, która przeciągnie tłumy na jego stronę?
Dziś wieczór, panie i panowie, się dowiemy.
Obstawiajcie. I cieszcie się walką!
🤣🤣🤣🤣🤣🤣🤣🤣🤣🤣🤣🤣🤣🤣🤣🤣🤣🤣
Ostatnio poproszono mnie o wyjaśnienie różnic między moim pluginem, Gato GraphQL, a WPGraphQL.
Oba pluginy są serwerami GraphQL dla WordPress, więc służą temu samemu celowi. Jednak pod maską mają różne cechy, które mogą sprawić, że jeden będzie lepszy od drugiego w zaspokojeniu określonych wymagań.
Choć jestem stronniczy wobec własnego pluginu, starałem się sporządzić rzetelne porównanie, oparte na tematach, które uważam za ważne zarówno dla GraphQL, jak i dla WordPress. (Jeśli czytelnicy chcieliby porównania na inny temat, chętnie się dostosuję.)
Porównanie nie jest wyczerpujące. Na przykład chciałbym też przeprowadzić benchmarki, mierząc szybkość rozwiązywania tego samego zapytania GraphQL z oboma serwerami. (Jeśli czytelnicy uznają tę propozycję za interesującą, mogę to zrobić w kolejnym artykule.)
Podzieliłem porównanie na 4 główne obszary: Popularność, Styl kodu i standardy, Pilne kwestie oraz Poszerzanie zakresu, z 3 elementami dla każdego, co daje łącznie 12 "rund". Na końcu sędziowie ogłaszają swój werdykt i wyłaniają mistrza.
Kliknij poniżej, aby przejść bezpośrednio do wybranego tematu:
🔔 Ding 🔔 ding 🔔 diiiiiing...
Dzwonek otwierający zabrzmiał...
Walka się rozpoczęła!
Popularność
Każde oprogramowanie (lub technologia) musi być używane przez ludzi — inaczej to, że jest lepsze od alternatyw, pozostanie jedynie anegdotą.
Na przykład, choć istnieją alternatywy pozwalające pisać szybciej, nadal używamy głównie klawiatury QWERTY.
Jak popularne są oba pluginy?
Round 1: Kto tego używa i jak kompletne to jest
WPGraphQL był do tej pory synonimem GraphQL w WordPress. Przez ponad 4 lata rozwoju (od listopada 2016 r.) zebrał ponad 2,8 tys. gwiazdek w repozytorium, społeczność ponad 4600 obserwujących oraz prawie 100 współtwórców projektu.
Osiągnął wersję 1.0 i został opublikowany w katalogu pluginów wp.org w listopadzie 2020 r. Od tego czasu zebrał ponad 8000 aktywnych instalacji. Jest obecnie jedynym rozwiązaniem do pobierania treści WordPress do Gatsby i od niedawna kilka projektów dodało go do swoich stosów, w tym framework Headless WPEngine oraz starter WordPress Next.js od WebDevStudios.
Innymi słowy, WPGraphQL jest popularny.
Rozwój Gato GraphQL rozpoczął się na dobre około 1,5 roku temu (jako część szerszego projektu) i osiągnął status "wystarczająco dobry" 6 miesięcy temu, zbierając od tamtej pory 150 gwiazdek w repozytorium. Plugin jest aktualnie w wersji 0.7 i do wersji 1.0 pozostało jeszcze kilka miesięcy (na przykład wciąż brakuje kategorii w schemacie).
W zeszłym miesiącu uruchomiłem obecną stronę gatographql.com i od tej pory promuję plugin przez blog (jak artykuł, który właśnie czytasz), a także opublikowałem artykuł wprowadzający na CSS-Tricks. Te działania przyciągnęły kilkaset osób na stronę, a ponad 100 odwiedzających pobrało plugin.
Innymi słowy, Gato GraphQL powoli, ale systematycznie zyskuje popularność i jest wciąż w fazie rozwoju.
Zwycięzca rundy: WPGraphQL.

Round 2: Dostępność rozszerzeń
Rozszerzenia umożliwiają interakcję z innymi pluginami za pośrednictwem Gato GraphQL.
WPGraphQL posiada rozszerzenia dla ACF, WooCommerce, Yoast i kilku innych.
Gato GraphQL nie ma jeszcze żadnych rozszerzeń i nie spodziewam się, że pojawi się ich wiele przed wydaniem wersji 1.0.
Jednak Gato GraphQL kładzie duży nacisk na rozszerzenia w swojej architekturze, pozwalając użytkownikowi zarządzać nimi (włączać, wyłączać, konfigurować i czytać ich dokumentację) z jednego centralnego miejsca — strony "Modules":

Innymi słowy, podczas gdy WPGraphQL ma już rozszerzenia, Gato GraphQL przygotowuje pod nie grunt.
Zwycięzca rundy: WPGraphQL.

Round 3: Docelowi odbiorcy
WPGraphQL jest skierowany do deweloperów: jeśli chcesz wyodrębnić dane ze swojej strony WordPress, musisz przechowywać zapytanie GraphQL gdzieś w kodzie (najprawdopodobniej w jakiejś funkcji JavaScript). Następnie, aby móc z niego korzystać, musisz być wystarczająco dobry w programowaniu.
Gato GraphQL natomiast podąża za filozofią WordPress, że każdy powinien być w stanie z niego korzystać, w tym osoby nietechniczne. Aby osiągnąć ten cel, umożliwia tworzenie i zarządzanie zapytaniami GraphQL za pomocą edytora WordPress, dzięki czemu udostępnienie danych strony WordPress przez API staje się tak proste jak stworzenie wpisu na blogu.
Ponadto Gato GraphQL kładzie większy nacisk na oferowanie klientów do interakcji z usługą GraphQL w sposób wizualny. Podczas gdy oba pluginy dostarczają klienta GraphiQL do wykonywania queries, tylko Gato GraphQL oferuje również klienta Voyager do interaktywnego eksplorowania schematu:

Zwycięzca rundy: Gato GraphQL.

Styl kodu i standardy
Porozmawiajmy o kodzie!
Jeśli używasz GraphQL, istnieje duże prawdopodobieństwo, że tworzysz headless WordPress i renderujesz stronę za pomocą jakiegoś frameworka JavaScript, co jest nowoczesnym paradygmatem. Co więcej, WordPress może być starym CMSem, ale GraphQL to nowoczesny interfejs dostępu do danych ze strony. Dlatego mogę śmiało założyć, że jesteś wymagającym deweloperem, dbającym o elegancki kod, i nie zaakceptujesz używania suboptymalnego rozwiązania.
Jak elegancki jest kod (zarówno w ich własnej bazie kodu, jak i oczekiwany od naszych niestandardowych implementacji) tych dwóch pluginów?
Round 4: Wymagania PHP
Zarówno WPGraphQL, jak i Gato GraphQL wymagają PHP 7.1+.
Istnieje jednak różnica: Gato GraphQL jest faktycznie kodowany przy użyciu PHP 7.4, a następnie transpilowany do PHP 7.1 na potrzeby produkcji.
Dlatego kodowanie Gato GraphQL jest o wiele przyjemniejsze: możesz korzystać z nowszych funkcji PHP, w tym typu object, właściwości typowanych oraz arrow functions. A gdy zostanie dodana obsługa PHP 8.0 (co nastąpi po wydaniu nowej wersji Lando), będziesz mógł też używać union types, wyrażenia match i innych.
Zwycięzca rundy: Gato GraphQL.

Round 5: Praktyki kodowania
Zacznijmy od WPGraphQL. Po wejściu do repozytorium wp-graphql/wp-graphql coś od razu rzuca mi się w oczy:

Przybliżając:

Przepraszam, ale mogę na to zareagować tylko w jeden sposób:

Commitowanie folderu vendor Composera do repozytorium to zła praktyka, a Composer wprost tego odradza.
Naprawienie tego problemu nie jest trudne (nawet opisałem sposób oparty na GitHub actions), więc zastanawiam się, dlaczego tak jest.
Powiedziałbym, że w tej rundzie WPGraphQL uderza sam siebie!

Kontynuując. Tworzenie dla WPGraphQL wymaga znajomości niezwykle rozbudowanej kolekcji hooków (actions i filters). Po przejściu do dokumentacji dla deweloperów WPGraphQL można docenić jej zakres.
Aby zrobić zrzut ekranu listy actions, musiałem pomniejszyć widok przeglądarki do 50%:

Dla listy filters zmniejszyłem do 30% (najniższy poziom obsługiwany przez Firefox), i nawet wtedy nie udało mi się uchwycić całej listy:

Przejdźmy do repozytorium GatoGraphQL/GatoGraphQL, czyli monorepozytorium zawierającego Gato GraphQL (wśród innych projektów).
Oto kilka cech kodu:
✅ Zgodny ze standardami PSR-1, PSR-4 i PSR-12.
✅ Cały kod jest podzielony na wiele atomowych pakietów, a wszystkie z nich (ponad 100 dla pluginu, ponad 200 dla całego projektu) są hostowane w tym samym monorepozytorium.
✅ Używa Composera do zarządzania wszystkimi zależnościami.
✅ Używa Symfony Dependency Injection do zarządzania wszystkimi usługami w aplikacji. Aby zarejestrować nowy type resolver, field resolver lub directive resolver, wystarczy zarejestrować nową usługę w kontenerze.
✅ Każda klasa jest usługą, a Symfony Dependency Injection zajmuje się automatycznym łączeniem całej aplikacji.
✅ Bazowy serwer GraphQL jest CMS-agnostic. Gato GraphQL implementuje kontrakty dla WordPress i dodaje nieco niestandardowej logiki (na przykład do dostarczania klientów).
Kod specyficzny dla WordPress stanowi tylko około 10% całego kodu. Powielenie tych 10% dla innego frameworka lub CMSa (Laravel/Drupal/itp.) może zapewnić implementację serwera GraphQL dla nich również.
✅ W konsekwencji bycia CMS-agnostic, kodowanie resolvera oznacza kodowanie jego ogólnej logiki biznesowej, zasilanej przez wielokrotnego użytku usługi. Nigdy nie myślimy w kategoriach kodu WordPress i rzadko musimy radzić sobie z jego długiem technicznym.
✅ Podobnie schemat GraphQL nie jest kopią 1:1 modelu danych WordPress, omijając dług techniczny zgromadzony przez WordPress w warstwie danych i zapewniając czysty interfejs.
✅ Problem N+1 GraphQL nie może wystąpić z założenia architektonicznego, bez żadnych kłopotów dla dewelopera.
✅ Serwer to nie tylko serwer GraphQL: to właściwie serwer API, gdzie odpowiedź może być generowana w innych formatach lub specyfikacjach (np. REST) z jednego źródła prawdy. (Więcej na ten temat w rundzie 11).
✅ Żaden folder vendor nie jest commitowany. Zamiast tego kod źródłowy jest przekształcany w kod dystrybucyjny (tj. finalny plugin do zainstalowania na stronie WordPress) za pomocą GitHub actions i wdrażany do repozytorium dist, gdzie folder vendor jest już zawarty.
✅ Podczas generowania kodu do dystrybucji, jest on opatrzony zakresem za pomocą PHP-Scoper, a kod źródłowy zawierający kod PHP 7.4 jest transpilowany do PHP 7.1.
✅ Dzięki rozwiązaniu problemu scopingu plugin może polegać na dowolnej zależności zewnętrznej. Obecnie korzysta z DependencyInjection Symfony, Cache i Dotenv, Guzzle (do interakcji z zewnętrznymi API), Pipeline League oraz kilku innych.
Jest to ważne nie tylko dla teraźniejszości, ale i dla przyszłości: mam pewność, że mogę używać dowolnej zależności z repozytorium Packagist, więc nie muszę wynajdywać koła od nowa.
✅ Pola są subskrybowane do typów, co ułatwia rozszerzanie schematu GraphQL.
Zwycięzca rundy: Gato GraphQL (ze znaczną przewagą, ośmielam się powiedzieć, jeśli nie masz nic przeciwko).

Round 6: Rozszerzanie schematu
Dodajmy pole do schematu GraphQL.
Korzystamy z tutoriala dla WPGraphQL. Sugerowany kod jest poniżej. Deklaruje action hooka do wykonania funkcji, która deklaruje tablicę. Zarówno opis pól, jak i ich rozwiązanie są dostarczane wewnątrz tablicy:
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';
},
]);
});Ten przykład jest tak prosty, jak to tylko możliwe: resolver praktycznie nic nie robi. A jednak już mam trudność z patrzeniem na ten kod i natychmiastowym zrozumieniem, co robi. Nie, nie jestem złośliwy: wszystkie kolory tego kodu w moim edytorze walczą o moją uwagę. Ponadto nie ma rozdzielenia odpowiedzialności, a kod nie wydaje się zbyt wielokrotnego użytku.
Dlatego to do dewelopera (czyli do ciebie) będzie należało sprawienie, by kod był czytelny, wielokrotnego użytku, wolny od błędów i wiele więcej podczas tworzenia aplikacji; sama biblioteka nie wydaje się tutaj zbytnio pomagać.
Nazywam ten styl "ADD": Array-Driven Development. Nie mogę powiedzieć, że jestem jego fanem.
(Aby być sprawiedliwym wobec WPGraphQL, jest to standardowa praktyka kodowania, stosowana również przez bazowy silnik webonyx/graphql-php.)
W Gato GraphQL cały kod jest SOLID. Aby zarejestrować pole w schemacie GraphQL, tworzymy klasę implementującą interfejs FieldResolverInterface (właściwie rozszerzając AbstractSchemaFieldResolver, który ma już wiele zaimplementowanych metod) i rejestrujemy ją w kontenerze.
Na przykład ten kod dostarcza pola username, email i url do typu 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;
}
}Uważam, że moje rozwiązanie jest bardziej eleganckie niż to z WPGraphQL. Jest to jednak kwestia gustu. Wiem, że wielu deweloperów nie ma nic przeciwko Array-Driven Development, a wręcz go preferuje, ponieważ w zwartym bloku kodu mogą zaimplementować całą logikę.
Zwycięzca rundy: remis.

Przerwa
Co za wieczór, panie i panowie.

Dotarliśmy do połowy walki, więc to dobry moment na przerwę i komentarz do tego, czego do tej pory doświadczyliśmy.
(W międzyczasie powinienem wyświetlić reklamę od moich sponsorów. Niestety, nie mam jeszcze żadnych. Jeśli chciałbyś, aby twoja firma sfinansowała rozwój Gato GraphQL i uzyskała ekspozycję w mediach pierwszej klasy, takich jak to wydarzenie, wyślij mi wiadomość.)

Co za walka! WPGraphQL był początkowo ogniem i furią! Wszedł do walki w świetnej formie, zadając Gato GraphQL niesamowicie potężne ciosy — ten ledwo mógł utrzymać się na nogach. Cios za ciosem za ciosem. Nie chciałbym być w butach Gato GraphQL.
Muszę przyznać, że po pierwszych 2 rundach myślałem, że walka wkrótce się skończy. Spodziewałem się nokdaunu w każdej chwili. Oczekiwałem, że zadrżeje ręcznik wzywający o litość. Ale Gato GraphQL wytrzymał. Musimy mu to oddać. Jakże niezachwiana determinacja, to naprawdę niezwykłe!
I wtedy nastąpiła przemiana. Gdzieś od 3. rundy Gato GraphQL zdawał się czerpać energię znikąd i zaczął nie tylko się bronić, ale oddawać ciosy, wiele z których trafiało WPGraphQL w twarz. Widziałem, jak WPGraphQL drżał i chwiał się! Czegoś takiego nigdy nie widzieliśmy u naszego obecnego mistrza świata. Co za naprawdę niezwykła przemiana, której właśnie byliśmy świadkami!
A potem, mając zachwianą pewność siebie przeciwnika, od 4. rundy Gato GraphQL wziął na siebie zadanie zadania serii śmiertelnych ciosów. To było zdumiewające! Na szczęście mierzy się z naszym mistrzem świata, WPGraphQL, który zdołał wytrzymać ciosy, wspomagany przez okrzyki i współczucie tłumów. Co za bohater! Każdy inny upadłby na miejscu, ale nie on — wytrzymał ciosy jak mistrz, którym jest.
Ale jak długo jeszcze będzie mistrzem? Nikt jeszcze nie upadł na ring, nikt nie rzucił ręcznika. Walka może w każdej chwili przybrać decydujący obrót. Dwaj zawodnicy wiedzą, czego chcą, i jestem pewien, że wrócą ze wszystkimi siłami i całą determinacją, by zaatakować przeciwnika i zwyciężyć.
Co za walka!
A teraz, panie i panowie, dwaj wojownicy wracają na ring.

Do reszty walki!
Pilne kwestie
Serwer GraphQL musi brać pod uwagę wiele kwestii, tylko po to, by spełnić obietnicę "pobierz dane, których potrzebujesz — nic więcej, nic mniej".
Na przykład:
- Jak jest bezpieczny? Jak upewnić się, że nie ujawniamy prywatnych danych na publicznym endpoincie?
- Jak wydajny jest? Jak możemy zmniejszyć obciążenie serwera przy wielokrotnym wysyłaniu tego samego zapytania, jednocześnie czyniąc go jak najszybszym?
- Jak prosty jest? Jak dobrze jest zintegrowany z WordPress, by móc korzystać z funkcji oferowanych przez CMS?
I wiele innych pytań. To tylko mała próbka, którą wybrałem i którą omówię w kolejnych 3 rundach.
Round 7: Persisted queries
Persisted queries łączą to, co najlepsze w GraphQL i REST: są tworzone przy użyciu GraphQL, więc nie ma niepełnego ani nadmiernego pobierania danych, ale są publikowane na serwerze jako endpoint z własnym URL.
Persisted queries oferują następujące korzyści:
✅ Jest bezpieczny: zamiast dawać dostęp do dowolnych danych przez pojedynczy endpoint, możemy z góry zdefiniować, jakie dane ujawniać.
✅ Jest szybki: dostępny przez własny URL, może być buforowany na każdej warstwie między klientem a backendem (na serwerze, CDN, przeglądarce) przy użyciu standardowego HTTP caching.
WPGraphQL oferuje obsługę persisted queries za pośrednictwem tych dwóch rozszerzeń:
Ponadto Jason Bahl (twórca WPGraphQL) niedawno ogłosił, że w najbliższej przyszłości doda obsługę persisted queries w WPGraphQL.
Zastanawiam się, co ma na myśli, skoro istnieją już 2 rozszerzenia. Czym będzie się różnił od nich? Może chce uczynić to częścią rdzenia pluginu, aby wzmocnić ogólne środki bezpieczeństwa bez polegania na zewnętrznych dostawcach?
A może zobaczył implementację Gato GraphQL i chce zapewnić podobne doświadczenie, obsługując je przez wizualny edytor zamiast czystego kodu?
Co prowadzi nas do Gato GraphQL. Nie tylko oferuje persisted queries, ale dążył do uczynienia ich centralną częścią oferty:
✅ Plugin umożliwia wyłączenie pojedynczego endpointu, a użytkownicy są zachęcani do ujawniania danych wyłącznie przez persisted queries.
(W przeciwieństwie do tego, WPGraphQL jedynie domyślnie wyłącza introspekcję, a nie sam endpoint. Innymi słowy, atakujący nadal mogą być w stanie uzyskać dostęp do prywatnych danych; po prostu utrudnia im się to zadanie, ponieważ z góry nie będą wiedzieć, jakie prywatne dane istnieją.)
✅ Jest głęboko zintegrowany z edytorem WordPress, dzięki czemu tworzenie persisted query wymaga tyle samo wysiłku co stworzenie wpisu na blogu, i może to zrobić każdy, nie tylko programiści.
✅ Persisted queries nie są statyczne: mogą używać zmiennych GraphQL, których wartość może być dostarczana przez parametry URL podczas wykonywania endpointu.
Sprawdź doświadczenie tworzenia i wykonywania persisted query w moim pluginie:
Zwycięzca rundy: Gato GraphQL.
Round 8: Caching
GraphQL ma duży problem: nie jest łatwy do buforowania. Powodem jest zależność od wysyłania operacji POST do pojedynczego endpointu. Ponieważ pojedynczy endpoint będzie dawał różne wyniki, a zapytanie jest wysyłane w treści żądania zamiast w parametrach URL, nie możemy buforować pojedynczego endpointu.
Standardowym rozwiązaniem oferowanym przez wiele serwerów GraphQL jest przeniesienie buforowania na klienta i poleganie na ID obiektów jako identyfikatorach encji do buforowania zamiast URL endpointu. Najpopularniejszą biblioteką zapewniającą tę funkcjonalność jest klient Apollo.
Na forum w repozytorium WPGraphQL omawiane są wszystkie opcje buforowania dla WPGraphQL. Co ciekawe, większość z nich to zewnętrzne narzędzia (takie jak klient Apollo czy WordPress Object Cache), co oznacza dodanie dodatkowej warstwy do aplikacji, zwiększając jej złożoność i ewentualnie spowalniając ją.
(Te powody muszą być częściowo za decyzją o natywnym implementowaniu persisted queries w WPGraphQL.)
Na przykład klient Apollo działa, cóż, po stronie klienta. Jeśli ktoś odwiedza stronę z niedrogiego telefonu komórkowego, ten dodatkowy kod JavaScript uderzy w wydajność aplikacji.
Podobnie deweloperzy pracujący z WordPress mogą być biegli w PHP, ale niekoniecznie w JavaScript. Teraz buforowanie ich API będzie oznaczać, że muszą martwić się również o warstwę JavaScript.
Gato GraphQL podszedł do tego tematu mądrzej. Ponieważ oferuje persisted queries, czyli queries są wykonywane na własnym endpoincie, umożliwia buforowanie tych URL endpointów przez HTTP caching.
Nagłówek HTTP caching ma wartość max-age automatycznie obliczaną ze wszystkich wartości max-age wszystkich pól w zapytaniu, a informacje te są konfigurowane przy użyciu edytora WordPress, pole po polu.
W konsekwencji API może być buforowane na wielu warstwach (w kliencie, CDN i serwerze) i jest obsługiwane natywnie w pluginie, bez potrzeby dodawania kolejnej warstwy.
Sprawdź ten film pokazujący, jak endpointy API są buforowane:
Zwycięzca rundy: Gato GraphQL.
Round 9: Integracja z Gutenbergiem
Kiedyś Gutenberg miał być przyszłością WordPress. Już nie: Gutenberg jest teraz teraźniejszością WordPress (możemy więc nazywać go edytorem WordPress), a Full Site Editing stał się nową przyszłością.
Nie trzeba mówić, że nasze API muszą być dobrze zintegrowane z edytorem WordPress. Oznacza to nie tylko pobieranie i publikowanie danych dla bloków, ale także potencjalne zasilanie funkcji w samym edytorze WordPress.
Na przykład, ponieważ subskrypcje GraphQL mogą sprawić, że serwer będzie w czasie rzeczywistym przesyłał dane do klienta, byłyby odpowiednie do zasilania funkcji współpracy edytorskiej i powiadomień.
WPGraphQL może pobierać dane bloków za pośrednictwem rozszerzenia WPGraphQL Gutenberg. Rozszerzenie to tworzy nowy typ dla każdego bloku, więc mamy CoreParagraphBlock, CoreQuoteBlock itp.
Gato GraphQL wkrótce będzie mógł pobierać dane bloków (jest to praca w toku). Jednak zamiast tworzyć nowy typ dla każdego bloku, będzie miał jeden typ Block do reprezentowania wszystkich bloków, a następnie będziemy mogli wyodrębnić określone metadane dla danego bloku na podstawie jego nazwy.
Na przykład sprawdź, jak możesz przetłumaczyć zawartość wewnątrz bloku akapitu (używając dyrektywy @strTranslate, która łączy się z 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")
}
}Zwycięzca rundy: remis.
Poszerzanie zakresu
"Mam marzenie."
Bloki Gutenberga zostały pomyślane jako ujednolicony interfejs do tworzenia treści w WordPress, znacznie upraszczając tworzenie kodu dla CMSa i naukę wymaganą od użytkowników.
Choć wprowadzone do tworzenia treści, bloki stopniowo przejmują wszystkie inne obszary CMSa, w tym widżety, menu i wkrótce motywy za pośrednictwem Full Site Editing. W przyszłości będą też obsługiwać możliwości wielojęzyczne i współpracę edytorską (funkcje, o których nie myślimy, gdy myślimy o blokach), i kto wie co jeszcze.
Możemy myśleć o GraphQL w tych samych kategoriach: jako o jednym interfejsie do interakcji z danymi. Oznacza to nie tylko pobieranie i publikowanie danych, ale wszelką interakcję obejmującą dane, w tym edycję.
WordPress ma wyjątkową szansę, by naprawdę stać się systemem operacyjnym sieci: system zasilany przez Gutenberga, który pozwala użytkownikowi wprowadzać dowolny rodzaj treści (tekst, obrazy, wideo, audio itp.), przetwarzać je za pomocą własnych narzędzi lub jakiejś usługi w chmurze, i publikować w docelowym miejscu — czy to na stronie WordPress, czy gdzie indziej.
Ale za tym potężnym marzeniem musi stać naprawdę potężne API, zdolne sprostać wszelkim wymaganiom, jakie mu stawiamy. API, które mogłoby opierać się na GraphQL, ale zostało zaprojektowane, by także transcendować jego ograniczenia.
Round 10: Obsługa niestandardowych dyrektyw

WPGraphQL nie jest dostarczany z ani jedną dyrektywą. Nie mówię, że ich nie obsługuje (silnik webonyx/graphql-php obsługuje), ale że nie oferuje implementacji żadnej niestandardowej dyrektywy.
"I co z tego?" możesz pomyśleć. "Po co nam dyrektywy? Jeśli ktoś chce zmodyfikować wynik zapytania, może to zrobić po stronie klienta!"

To kwestia opinii i nie ma tu dobrego czy złego. Ale pozwól, że ci powiem: dyrektywy są niesamowicie użyteczną funkcją, która pomaga wyróżnić GraphQL od REST. Jeśli ich nie używasz, najprawdopodobniej nie wyciągasz maksimum ze swojego API.
Dyrektywy są nieuregulowane przez specyfikację, więc serwery GraphQL mogą je implementować w dowolny sposób i czynić tak potężnymi, jak potrzebują. Dlatego wiele nowych funkcji w GraphQL jest najpierw wprowadzanych przez dyrektywy, takie jak @stream i @defer.
Gato GraphQL traktuje dyrektywy z szacunkiem. Są wykonywane tylko raz z danymi wszystkich encji, dla wszystkich pól, do których są stosowane (co wyjaśnia, dlaczego dyrektywa @strTranslate może tak szybko pobierać wyniki z API Google Translate), a sam silnik GraphQL oparty jest na potoku dyrektyw.
Ahhhh, ale boisz się udostępniać użytkownikom całą tę moc, prawda? To uzasadniona obawa. Ale możesz po prostu usunąć dostęp do pojedynczego endpointu i zapewnić dostęp do danych wyłącznie przez persisted queries, gdzie ty (administrator strony) jesteś jedyną osobą mającą dostęp do dyrektyw.
Więc albo zyskujesz, albo nic się nie dzieje.
Jeśli kochasz dyrektywy, świetnie — pokochasz Gato GraphQL! ❤️
Ale z drugiej strony, jeśli nie lubisz, nic się nie dzieje.
Zwycięzca rundy: Gato GraphQL.
(Jeśli uważasz, że "nie potrzebujemy żadnych śmierdzących dyrektyw", proszę, nie gniewaj się na mnie... Po prostu wykonuję swoją pracę.)
Round 11: Obsługa REST
"Ahhhhh? REST? Jaki REST? Czy nie rozmawiamy tu o GraphQL? Dlaczego mówisz o REST? Dlaczego chcesz komplikować mi życie?"

Tak, na pierwszy rzut oka ten temat wydaje się nie na miejscu. Ale dodałem go do tego porównania z bardzo prostego powodu: Matt Mullenweg powiedział, że analizuje GraphQL pod kątem ewentualnego włączenia do rdzenia WordPress, a jedyną rzeczą, o którą martwić się będą współtwórcy, jest konieczność utrzymywania dwóch baz kodu.
Co prowadzi do oczywistego pytania: czy serwer GraphQL może obsługiwać również REST?
Odpowiedź brzmi "częściowo tak" dla WPGraphQL i "całkowicie tak" dla Gato GraphQL.
Jeśli chodzi o WPGraphQL. Możliwe jest zdefiniowanie endpointu REST, który po uruchomieniu po prostu wykonuje zapytanie GraphQL zawierające wymagane pola, albo jako wewnętrzne wywołanie silnika GraphQL, albo jako zewnętrzna operacja POST wykonywana na tym samym serwerze webowym.
Ale to nie wystarczy, by spełnić wymagania WP REST API, ponieważ posiada ono również schemat JSON, bez którego nie możemy się obejść.
Jeśli chodzi o Gato GraphQL. Muszę przyznać, że miałem szczęście, ponieważ prace nad jego bazowym silnikiem (po stronie serwera model komponentów o nazwie PoP) rozpoczęły się około 2013 roku, czyli kilka lat przed tym, nim dowiedziałem się o czymś takim jak GraphQL, a projekt ten ewoluował z własnymi pomysłami (które udokumentowałem w tym moim vintage artykule).
Następnie, gdy zacząłem kodować CMS-agnostic serwer GraphQL (na którym opiera się Gato GraphQL) około 1,5 roku temu, połączyłem pomysły opracowane dla PoP z fundamentami ustanowionymi przez GraphQL, tworząc system obsługujący specyfikację GraphQL w całości, będąc jednocześnie w stanie dodawać do niego inny zestaw funkcji.
W tym sensie schemat używany przez PoP jest API-agnostic i jest nadzbiorem schematu GraphQL. Schemat PoP jest dostępny pod /api/graphql/?query=fullSchema.
Następnie warstwa serwera GraphQL formatuje schemat PoP zgodnie ze specyfikacją GraphQL, co daje schemat GraphQL. Podobnie możemy wygenerować schemat JSON wymagany przez WP REST API.
Wygenerowanie tego schematu JSON nie zostało jeszcze zrobione, ale jest wykonalne.
To, co już zostało zrobione, to generowanie odpowiedzi zapytania w wielu formatach. Na przykład to zapytanie GraphQL:
{
posts {
id
title
date
author {
name
}
}
}Jest też rozwiązywane przez ten endpoint REST: /posts/api/rest/?query=id|title|date|author.name.
I nie musimy tu się zatrzymywać. Potrzebujesz wygenerować wyniki w jeszcze innym formacie, takim jak XML? Żaden problem: /api/?query=posts.id|title|date|author.name&datastructure=xml.
(Mogłoby to pomóc we wdrożeniu propozycji nowego narzędzia importu/eksportu dla WordPress opartego na schemacie. To także nieco bardziej uwydatnia to, co powiedziałem wcześniej: jeden interfejs może obsługiwać wszelkie interakcje z danymi, zarówno wewnątrz CMSa, jak i między CMSem a zewnętrznymi API.)
Zwycięzca rundy: Gato GraphQL.
Round 12: Obsługa nowatorskich funkcji
Czy specyfikacja GraphQL jest ostateczna? Odpowiedź brzmi nie: specyfikacja stale ewoluuje. W tej chwili otwartych jest 100 zgłoszeń, wiele z nich zawierających propozycje, które zostaną sformalizowane w przyszłości.
Wśród tych 100 zgłoszeń z pewnością znajdą się nowe funkcje, z których możemy korzystać już dziś, prawda? Jeśli tak, to po co czekać?
Dokładnie tak myślę.

"Ale jeśli coś nie jest w specyfikacji GraphQL, to nie powinniśmy tego dodawać do serwera GraphQL, bo użytkownicy się pogubią!"
Dobry punkt. Jednak jeśli udostępnimy nowe funkcje wyłącznie jako opt-in, użytkownicy będą świadomie z nich korzystać i nie pojawi się żaden problem czy nieporozumienie.
Po raz kolejny, tak właśnie myślę. Jest to jednak kwestia opinii, więc jeśli wolisz używać wyłącznie funkcji obsługiwanych przez każdy istniejący serwer GraphQL, to jest w porządku.
Uważam, że w ten sposób działa WPGraphQL. Przynajmniej nie widziałem ani jednej funkcji wykraczającej poza to, co zostało zatwierdzone w specyfikacji.
Jeśli chodzi o Gato GraphQL, regularnie przeglądam listę zgłoszeń w specyfikacji i jeśli znajdę jakąś fajną funkcję, którą mój serwer może obsłużyć bez większego wysiłku, to ją implementuję. (Właściwie to jeden z moich hobbystycznych projektów.)
Oto funkcje "skierowane w przyszłość", które zaimplementowałem do tej pory:
✅ Wykonywanie wielu queries
✅ Przestrzenie nazw schematu
✅ Zagnieżdżone mutacje
✅ Kompozytywne dyrektywy
✅ Proaktywna informacja zwrotna
✅ Wersjonowanie oparte na polach i dyrektywach
I już planuję dodać:
✳️ Subskrypcje (to już jest częścią specyfikacji)
✳️ Dyrektywy @stream i @defer
✳️ Składnia płaskiego łańcucha
Zwycięzca rundy: Gato GraphQL.
Werdykt!
Panie, panowie.

Co za niezapomniana noc! Co za walka, której właśnie byliśmy świadkami! Dwóch ciężkich ciężkociężkich dających z siebie wszystko w walce o marzenie.
Marzenie, za którym obaj gonią, ale które może złapać tylko jeden z nich.
A teraz dowiemy się, kto to jest. Teraz czas na prawdę!
Kto będzie mistrzem świata "GraphQL w WordPress"?
Czy będzie to powszechnie uznawany, uwielbiany przez masy, pojawiający się w wielkich publikacjach, obecny mistrz, WPGraphQL?
Czy może będzie to niepokorny, depczący-ci-po-odciskach-bez-przeproszenia, przychodzący-niezaproszony-na-przyjęcie pretendent, Gato GraphQL?

Czekamy na werdykt sędziego. Co za napięcie! O Matko Boska, spraw, by moje serce wytrzymało tę chwilę!
🥁 I 🥁 zwycięzcą 🥁 jestttttttttttt 🥁 ...
To remis!
2 zawodników, 2 ciężkociężkich — remis!

Co za wspaniały moment! Dwaj zawodnicy obejmują się, pokazując, że wszyscy jesteśmy przyjaciółmi w społeczności WordPress, jak jedna wielka rodzina.
Więc jakie jest uzasadnienie remisu? Sędzia wyjaśnia:
👑 WPGraphQL jest popularniejszy i jego użycie jest bardziej powszechne.
👑 Gato GraphQL ma lepszą architekturę i potencjalnie może lepiej służyć WordPress w dłuższej perspektywie.
Panie i panowie, usłyszeliście werdykt sędziego!
A nasz trofeum ma dwie rękawice: po jednej dla każdego zawodnika.

Ale jaki jest twój werdykt?
Czy będziesz bezwarunkowo używać WPGraphQL do swoich potrzeb headless?
Czy dasz Gato GraphQL szansę, o którą się upomina, pobierz plugin i wypróbuj go?
Panie i panowie. To wszystko na dziś wieczór.
Szczerze mamy nadzieję, że podobała wam się walka.
I miejmy nadzieję, że wkrótce będziemy mieli nowe spotkanie naszych dwóch mistrzów.
Dobranoc.
Aktualizacja 01/05/2024: Dowiedz się więcej w porównaniu Gato GraphQL vs WPGraphQL.