Blog

🥊 Gato GraphQL vs WPGraphQL: de strijd!

Leonardo Losoviz
Door Leonardo Losoviz ·

Update 01/05/2024: Bekijk de vergelijking Gato GraphQL vs WPGraphQL.

Daaaaaaames en heren.

Aankondiging van de aankomende wedstrijd

Welkom in de MGM Grand Garden Arena voor de kamp van de eeuw! Vanavond schrijven we geschiedenis. Twee jonge vechters staan tegenover elkaar in de ring, strijdend voor de prijs waarvoor ze zo hard hebben gewerkt:

De wereldkampioen "GraphQL in WordPress" worden 🏆

Aan onze rechterkant hebben we de huidige kampioen. Hoewel hij nog maar 4 jaar oud is, heeft hij al volop ervaring — hij bereikte onlangs versie 1.0 en werd gepubliceerd in de wp.org-directory, en hij is erg populair bij het publiek.

🥁 Geef 🥁 een 🥁 warm 🥁 welkom 🥁 aan 🥁 ...... WPGraphQL!

De huidige kampioen, WPGraphQL

Aan onze linkerkant hebben we de uitdager. Hij is pas 1 maand in de wereld, maar hij is vol energie en ambitie en toont zijn kracht vanaf de allereerste dag. Hij was degene die zocht naar de ontmoeting van vandaag. Vanavond is zijn kans, en de wereld kijkt toe.

🥁 Geef 🥁 een 🥁 warm 🥁 welkom 🥁 aan 🥁 ...... Gato GraphQL!

De uitdager, Gato GraphQL

Vanavond ontmoeten onze deelnemers elkaar voor het eerst van aangezicht tot aangezicht, in een kamp van 12 ronden. Terwijl ze hun posities innemen in het midden van de ring, wachtend op de openingsbel, bestuderen ze elkaar en proberen elkaars zwakke plekken te vinden. Ze tonen echter alleen maar zelfvertrouwen.

De 2 glorieuze vechters bestuderen elkaar

Wie zal er winnen? Zal WPGraphQL zijn voorsprong behouden, gebaseerd op de steun van zijn aanhangers? Of zal de nieuwkomer Gato GraphQL een nietsvermoedende gemeenschap overtuigen van de kracht van zijn vuisten, een spoor van ontzag achterlatend dat het publiek naar zijn kant trekt?

Vanavond, dames en heren, zullen we het weten.

Zet je in. En geniet van de wedstrijd!


🤣🤣🤣🤣🤣🤣🤣🤣🤣🤣🤣🤣🤣🤣🤣🤣🤣🤣


Onlangs werd me gevraagd de verschillen uit te leggen tussen mijn plugin, Gato GraphQL, en WPGraphQL.

Beide plugins zijn GraphQL-servers voor WordPress en dienen dus hetzelfde doel. Maar onder de motorkap hebben ze verschillende kenmerken, waardoor de ene beter kan zijn dan de andere om aan bepaalde vereisten te voldoen.

Hoewel ik bevooroordeeld ben ten opzichte van mijn eigen plugin, heb ik geprobeerd een eerlijke vergelijking te maken, gebaseerd op onderwerpen die ik belangrijk vind voor zowel GraphQL als WordPress. (Als lezers een vergelijking over een ander onderwerp willen, doe ik dat graag.)

De vergelijking is niet uitputtend. Ik zou bijvoorbeeld ook benchmarks willen doen, waarbij ik de snelheid meet van het oplossen van dezelfde GraphQL-query met beide servers. (Als lezers dit voorstel aantrekkelijk vinden, kan ik dat in een volgend artikel doen.)

Ik heb mijn vergelijking opgesplitst in 4 hoofdgebieden: Populariteit, Codeerstijl en standaarden, Dringende kwesties en De reikwijdte verbreden, met 3 onderdelen per gebied, voor een totaal van 12 "ronden". Aan het einde geven de rechters hun oordeel om de kampioen te benoemen.

Klik hieronder om direct naar een onderwerp te gaan:

🔔 Ding 🔔 ding 🔔 diiiiiing...

De openingsbel heeft geklonken...

De strijd is begonnen!


Populariteit

Elke software (of technologie, voor die matter) moet door mensen worden gebruikt — anders is het feit dat het beter is dan de alternatieven slechts een anekdote.

Hoewel er alternatieven zijn waarmee je sneller kunt typen, gebruiken we nog steeds voornamelijk het QWERTY-toetsenbord.

Hoe populair zijn de twee plugins?

Round 1: Wie gebruikt het, en hoe compleet is het

WPGraphQL was tot nu toe een synoniem voor GraphQL in WordPress. Gedurende de meer dan 4 jaar dat het is ontwikkeld (beginnend in november 2016) verzamelde het meer dan 2,8k sterren op de repo, een gemeenschap van meer dan 4600 volgers en bijna 100 bijdragers aan het project.

Het bereikte versie 1.0 en werd in november 2020 geüpload naar de plugin-directory op wp.org. Sindsdien heeft het meer dan 8000 actieve installaties verzameld. Het is momenteel de enige oplossing voor het ophalen van WordPress-inhoud naar Gatsby, en meer recentelijk hebben meerdere projecten het aan hun stacks toegevoegd, waaronder WPEngine's Headless framework en WebDevStudios' Next.js WordPress starter.

Met andere woorden: WPGraphQL is populair.

De ontwikkeling van Gato GraphQL begon serieus ongeveer 1,5 jaar geleden (als onderdeel van een breder project), en het bereikte 6 maanden geleden een "goed genoeg"-status, en verzamelde sindsdien 150 sterren op de repo. De plugin is momenteel op versie 0.7 en is nog enkele maanden verwijderd van versie 1.0 (het heeft bijvoorbeeld nog geen categorieën in het schema).

Vorige maand lanceerde ik de huidige site gatographql.com, en sindsdien promoot ik de plugin via de blog (zoals het artikel dat je nu leest), en publiceerde ik ook een intro-artikel op CSS-Tricks. Deze inspanningen hebben enkele honderden mensen naar de site gebracht, en meer dan 100 bezoekers hebben de plugin gedownload.

Met andere woorden: Gato GraphQL wordt langzaam maar gestaag populairder en is nog volop in ontwikkeling.

Winnaar van de ronde: WPGraphQL.

Een treffer! De stoot van WPGraphQL raakt Gato GraphQL

Round 2: Beschikbaarheid van extensies

Extensies maken het mogelijk om via Gato GraphQL met andere plugins te werken.

WPGraphQL heeft extensies voor ACF, WooCommerce, Yoast en een paar andere.

Gato GraphQL heeft nog geen extensies, en ik verwacht niet dat er veel zullen zijn voor de release van versie 1.0.

Maar Gato GraphQL legt een grote nadruk op extensies in zijn architectuur, waardoor de gebruiker ze (inschakelen, uitschakelen, configureren en hun documentatie lezen) vanuit één centrale plek kan beheren: de "Modules"-pagina:

Modules-pagina in Gato GraphQL

Met andere woorden: terwijl WPGraphQL al extensies heeft, bereidt Gato GraphQL het terrein daarvoor voor.

Winnaar van de ronde: WPGraphQL.

WPGraphQL slaat opnieuw!

Round 3: Doelgroep

WPGraphQL richt zich op ontwikkelaars: als je gegevens uit je WordPress-site wilt extraheren, moet je je GraphQL-query ergens in je code opslaan (waarschijnlijk in een JavaScript-functie). Om het vervolgens te kunnen gebruiken, moet je goed genoeg kunnen programmeren.

Gato GraphQL volgt daarentegen de WordPress-filosofie dat iedereen het moet kunnen gebruiken, inclusief niet-techneuten. Om dit doel te bereiken, kun je een GraphQL-query aanmaken en beheren via de WordPress-editor, zodat het beschikbaar stellen van de gegevens van je WordPress-site via een API net zo eenvoudig wordt als het schrijven van een blogpost.

Bovendien legt Gato GraphQL meer nadruk op het aanbieden van clients om visueel met de GraphQL-dienst te werken. Terwijl beide plugins de GraphiQL-client bieden om de query uit te voeren, biedt alleen Gato GraphQL ook de Voyager-client om het schema interactief te verkennen:

Het GraphQL-schema visualiseren

Winnaar van de ronde: Gato GraphQL.

Gato GraphQL geeft een goede linkse hoek!


Codeerstijl en standaarden

Laten we het over code hebben!

Als je GraphQL gebruikt, doe je waarschijnlijk headless WordPress en render je de website met een JavaScript-framework, wat een modern paradigma is. Bovendien is WordPress misschien een oud CMS, maar GraphQL is een moderne interface voor toegang tot gegevens van de site. Ik kan er dus veilig van uitgaan dat je een verstandige ontwikkelaar bent die elegante code wil maken en geen genoegen neemt met een suboptimale oplossing.

Hoe elegant is de code (van hun eigen codebase, en verwacht van onze aangepaste implementaties) van deze twee plugins?

Round 4: PHP-vereisten

Zowel WPGraphQL als Gato GraphQL vereisen PHP 7.1+.

Er is echter een verschil: Gato GraphQL is eigenlijk gecodeerd met PHP 7.4 en wordt vervolgens getranspileerd naar PHP 7.1 voor productie.

Het coderen van Gato GraphQL is daardoor veel aangenamer: je kunt nieuwere PHP-functies gebruiken, waaronder het object-type, typed properties en arrow functions. En zodra ondersteuning voor PHP 8.0 is toegevoegd (wat zal gebeuren wanneer de nieuwe versie van Lando wordt uitgebracht), kun je ook union types, de match-expressie en andere gebruiken.

Winnaar van de ronde: Gato GraphQL.

Gato GraphQL laat zijn stempel achter!

Round 5: Codeerpraktijken

Laten we beginnen met WPGraphQL. Wanneer je naar de wp-graphql/wp-graphql-repo gaat, valt er meteen iets op:

De vendor-map opgeslagen in de repo

Inzoomen:

Inhoud van de vendor-map

Sorry, maar er is maar één manier waarop ik hierop kan reageren:

Ik kan je veel dingen in het leven vergeven, maar dit niet

De vendor-map van Composer committen naar de repo is een slechte praktijk, en Composer raadt dit expliciet af.

Dit probleem oplossen is niet moeilijk (ik heb zelfs een methode beschreven op basis van GitHub actions), dus ik vraag me af waarom het er staat.

Ik zou zeggen dat in deze ronde WPGraphQL zichzelf slaat!

Ai!

Verder. Ontwikkelen voor WPGraphQL vereist kennis van een enorm uitgebreide verzameling hooks (actions en filters). Wanneer je naar WPGraphQL's Ontwikkelaarsreferentie gaat, kun je de omvang hiervan waarderen.

Om een screenshot te maken van de lijst met actions moest ik mijn browser uitzoomen naar 50%:

Action hooks voor het uitbreiden van WPGraphQL

Voor de lijst met filters zoomde ik uit naar 30% (het laagste dat Firefox ondersteunt), en zelfs dan kon ik de volledige lijst niet in beeld krijgen:

Filter hooks voor het uitbreiden van WPGraphQL


Laten we overstappen naar de GatoGraphQL/GatoGraphQL-repo, de monorepo die Gato GraphQL (onder andere projecten) bevat.

Dit zijn enkele kenmerken van de code:

✅ Voldoet aan de standaarden PSR-1, PSR-4 en PSR-12.

✅ Alle code is opgesplitst in meerdere, atomaire pakketten, en ze worden alle (meer dan 100 voor de plugin, meer dan 200 voor het hele project) gehost in dezelfde monorepo.

✅ Gebruikt Composer om alle afhankelijkheden te beheren.

✅ Gebruikt Symfony Dependency Injection om alle services in de applicatie te beheren. Om een nieuwe type resolver, field resolver of directive resolver te registreren, hoef je alleen maar een nieuwe service in de container te registreren.

✅ Elke class is een service, en Symfony Dependency Injection zorgt voor het autowiren van de hele applicatie.

✅ De onderliggende GraphQL-server is CMS-agnostisch. Gato GraphQL implementeert de contracten voor WordPress en voegt een beetje aangepaste logica toe (bijvoorbeeld voor het leveren van de clients).

De WordPress-specifieke code is slechts ongeveer 10% van de totale code. Dit 10% repliceren voor een ander framework of CMS (Laravel/Drupal/etc.) kan een implementatie van een GraphQL-server voor hen opleveren.

✅ Als gevolg van het CMS-agnostisch zijn, houdt het coderen van een resolver in dat je de generieke bedrijfslogica codeert, aangedreven door herbruikbare services. We denken nooit in termen van WordPress-code en we hoeven zelden met de technische schuld ervan om te gaan.

✅ Evenzo is het GraphQL-schema geen 1:1-replica van het WordPress-datamodel, waarmee de technische schuld die WordPress op de datalaag heeft opgebouwd wordt omzeild en een schone interface wordt geboden.

✅ Het N+1-probleem van GraphQL kan niet optreden, door architectuurontwerp, zonder de ontwikkelaar enige moeite te kosten.

✅ De server is niet alleen een GraphQL-server: het is eigenlijk een API-server, waarbij het antwoord in andere formaten of specificaties (bijv. REST) kan worden uitgeleverd vanuit één enkele bron van waarheid. (Meer hierover in ronde 11).

✅ Er wordt geen vendor-map gecommit. In plaats daarvan wordt de broncode omgezet naar distributiecode (d.w.z. de uiteindelijke plugin die op de WordPress-site wordt geïnstalleerd) via GitHub actions, en geïmplementeerd naar een dist-repo, waar de vendor-map wel aanwezig is.

✅ Bij het genereren van de code voor distributie wordt deze gescopet met PHP-Scoper, en de broncode, die PHP 7.4-code bevat, wordt getranspileerd naar PHP 7.1.

✅ Omdat het scoping heeft opgelost, kan de plugin vertrouwen op elke third-party afhankelijkheid. Momenteel maakt het gebruik van Symfony's DependencyInjection, Cache en Dotenv, Guzzle (voor interactie met externe API's), de League's Pipeline en verschillende andere.

Dit is niet alleen belangrijk voor het heden, maar ook voor de toekomst: ik kan er zeker van zijn dat ik elke afhankelijkheid uit de Packagist-repository kan gebruiken, zodat ik het wiel niet opnieuw hoef uit te vinden.

Velden zijn geabonneerd op types, waardoor het GraphQL-schema gemakkelijk uit te breiden is.

Winnaar van de ronde: Gato GraphQL (met een grote marge, durf ik te zeggen, als je het niet erg vindt).

Na een zware ronde heeft WPGraphQL wat rust nodig

Round 6: Het schema uitbreiden

Laten we een veld toevoegen aan het GraphQL-schema.

We volgen de tutorial voor WPGraphQL. De voorgestelde code staat hieronder. Het declareert een action hook om een functie uit te voeren die een array declareert. Zowel de beschrijving van de velden als de oplossing ervan wordt binnen de array opgegeven:

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';
		},
	]);
 
});

Dit voorbeeld is zo eenvoudig als het maar kan: de resolver doet eigenlijk niets. Toch heb ik al moeite om de code te bekijken en onmiddellijk te begrijpen wat hij doet. Nee, ik ben niet sarcastisch: alle kleuren van die code in mijn editor vechten om mijn aandacht. Bovendien is er geen scheiding van verantwoordelijkheden, en de code lijkt niet erg herbruikbaar te zijn.

Het zal dus aan de ontwikkelaar (dat wil zeggen aan jou) zijn om de code leesbaar, herbruikbaar, bugvrij en nog veel meer te maken bij het ontwikkelen van de applicatie; de bibliotheek zelf lijkt hier niet veel bij te helpen.

Ik noem deze stijl "ADD": Array-Driven Development. Ik kan niet zeggen dat ik er fan van ben.

(Om eerlijk te zijn tegenover WPGraphQL: dit is een standaard codeerpraktijk, en ook degene die wordt gebruikt door de onderliggende engine webonyx/graphql-php.)


In Gato GraphQL is alle code SOLID. Om een veld in het GraphQL-schema te registreren, maken we een class die interface FieldResolverInterface implementeert (eigenlijk uitbreidend van AbstractSchemaFieldResolver, dat al veel geïmplementeerde methoden heeft), en we registreren het in de container.

Bijvoorbeeld deze code biedt velden username, email en url aan het type 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;
  }
}

Ik geloof dat mijn oplossing eleganter is dan die van WPGraphQL. Maar dat is een kwestie van smaak. Ik weet dat veel ontwikkelaars geen moeite hebben met Array-Driven Development, en het zelfs de voorkeur geven omdat ze in een compact stuk code alle logica kunnen implementeren.

Winnaar van de ronde: gelijkspel.

Gelijkspel


Pauze

Wat een avond, dames en heren.

Tijd om de wedstrijd tot nu toe te analyseren

We hebben het midden van de strijd bereikt, dus dit is een goed moment voor een sanitaire stop en wat commentaar op wat we tot nu toe hebben meegemaakt.

(In de tussentijd zou ik een advertentie moeten tonen van mijn sponsors. Helaas heb ik er nog geen. Als je wilt dat je bedrijf de ontwikkeling van Gato GraphQL financiert en exposure krijgt in topmedium zoals dit evenement, stuur me dan een bericht.)

Word mijn sponsor, om toegang te krijgen tot toptoppromotie voor je merk

Wat een wedstrijd! WPGraphQL was aanvankelijk vuur en furie! Hij begon de wedstrijd in geweldige vorm en deelde verschrikkelijk zware klappen uit aan Gato GraphQL, die nauwelijks op zijn benen kon staan. Klap na klap na klap. Ik wilde niet in Gato GraphQL's schoenen staan.

Ik moet toegeven dat ik na de eerste 2 ronden dacht dat de wedstrijd snel voorbij zou zijn. Ik verwachtte elk moment de knock-down. Een wiebelende handdoek te zien die om genade smeekt. Maar Gato GraphQL hield stand. Dat moeten we hem nageven. Wat een onwrikbare vastberadenheid, het is werkelijk opmerkelijk!

En toen vond de transformatie plaats. Ergens vanaf de 3e ronde leek Gato GraphQL energie uit het niets te halen, en begon niet alleen zichzelf te verdedigen, maar sloeg terug, waarvan er velen het gezicht van WPGraphQL raakten. Ik zag WPGraphQL trillen en wankelen! Zoiets hadden we nog nooit gezien van onze huidige wereldkampioen. Wat een werkelijk opmerkelijke transformatie die we zojuist hebben meegemaakt!

En toen, nadat hij het zelfvertrouwen van zijn tegenstander had geschokt, nam Gato GraphQL het vanaf de 4e ronde op zich om een reeks dodelijke klappen uit te delen. Dat was verbazingwekkend! Gelukkig staat hij tegenover onze wereldkampioen, de WPGraphQL, en hij kon de klappen weerstaan, opgeheven door de aanmoedigingen en het medeleven van het publiek. Wat een held! Ieder ander zou ter plekke zijn gevallen, maar niet hij, hij doorstond de klappen als de kampioen die hij is.

Maar hoe lang is hij nog kampioen? Niemand is nog neergeslagen, niemand heeft de handdoek gegooid. De strijd kan elk moment een beslissende wending nemen. De twee vechters weten wat ze willen, en ik weet zeker dat ze met al hun kracht en vastberadenheid terugkomen om hun tegenstander aan te vallen en te overwinnen.

Wat een wedstrijd!

En nu, dames en heren, keren de twee strijders terug naar de ring.

De deelnemers keren terug naar de ring

Op naar de rest van de strijd!


Dringende kwesties

De GraphQL-server moet veel overwegingen in acht nemen, alleen maar om de belofte "haal de gegevens op die je nodig hebt, niets meer of minder" waar te maken.

Bijvoorbeeld:

  • Hoe veilig is het? Hoe zorgen we ervoor dat we geen privégegevens blootstellen op een openbaar endpoint?
  • Hoe performant is het? Hoe kunnen we de serverbelasting verminderen bij het steeds opnieuw verzenden van dezelfde query, terwijl het zo snel mogelijk is?
  • Hoe eenvoudig is het? Hoe goed is het geïntegreerd met WordPress, om gebruik te maken van de functies die het CMS biedt?

En nog veel meer vragen. Dit is maar een klein voorbeeld dat ik heb gekozen en dat ik in de volgende 3 ronden zal behandelen.

Round 7: Persisted queries

Persisted queries combineren het beste van zowel GraphQL als REST: ze worden gemaakt met GraphQL, dus er is geen under/over fetching van gegevens, maar ze worden op de server gepubliceerd als een endpoint met zijn eigen URL.

Persisted queries bieden deze voordelen:

✅ Het is veilig: in plaats van toegang te geven tot elk stukje data via het enkele endpoint, kunnen we vooraf definiëren welke data we willen blootstellen.

✅ Het is snel: toegankelijk via zijn eigen URL, kan het worden gecached op elke laag tussen de client en back-ends (op de server, CDN, browser) via de standaard HTTP caching.

WPGraphQL biedt ondersteuning voor persisted queries via deze twee extensies:

Bovendien kondigde Jason Bahl (de maker van WPGraphQL) onlangs aan dat hij in de nabije toekomst ondersteuning voor persisted queries aan WPGraphQL zal toevoegen.

Ik vraag me af wat hij in gedachten heeft, want er zijn al 2 extensies. Hoe zal het anders zijn dan die? Misschien wil hij het onderdeel maken van de kern van de plugin, om de algehele beveiligingsmaatregelen van de plugin te versterken zonder afhankelijk te zijn van een derde partij?

Of heeft hij misschien de implementatie van Gato GraphQL gezien en wil hij een vergelijkbare ervaring bieden, waarbij het via een visuele editor wordt bediend in plaats van pure code?

Wat ons bij Gato GraphQL brengt. Het niet alleen biedt persisted queries, maar heeft ernaar gestreefd om dit een centraal onderdeel van het aanbod te maken:

✅ De plugin maakt het mogelijk het enkele endpoint uit te schakelen, en gebruikers worden aangemoedigd om gegevens alleen via persisted queries beschikbaar te stellen.

(WPGraphQL schakelt standaard alleen introspectie uit, niet het eigenlijke endpoint. Met andere woorden, aanvallers kunnen nog steeds toegang krijgen tot privégegevens; hun taak wordt alleen moeilijker gemaakt, omdat ze van tevoren niet weten welke privégegevens er zijn.)

✅ Het is diep geïntegreerd met de WordPress-editor, zodat het aanmaken van een persisted query evenveel moeite kost als het aanmaken van een blogpost, en iedereen het kan doen, niet alleen programmeurs.

✅ Persisted queries zijn niet statisch: ze kunnen GraphQL-variabelen gebruiken, waarvan de waarde via URL-parameters kan worden opgegeven bij het uitvoeren van het endpoint.

Bekijk de ervaring van het aanmaken en uitvoeren van een persisted query in mijn plugin:

Winnaar van de ronde: Gato GraphQL.

Round 8: Caching

GraphQL heeft een groot pijnpunt: het is niet gemakkelijk te cachen. De reden is dat het afhankelijk is van het verzenden van POST-bewerkingen naar een enkel endpoint. Omdat het enkele endpoint verschillende resultaten zal opleveren, en omdat de query wordt verzonden in de body van het verzoek in plaats van URL-parameters, kunnen we het enkele endpoint niet laten cachen.

De standaardoplossing die door veel GraphQL-servers wordt aangeboden, is om het cachen naar de client te verschuiven en te vertrouwen op object-ID's als identificatoren van de entiteit die gecached moet worden in plaats van de URL van een endpoint. De meest populaire bibliotheek die deze functionaliteit biedt is de Apollo client.

Er is een discussie in de WPGraphQL-repo over alle beschikbare cachingopties voor WPGraphQL. Interessant genoeg zijn de meeste ervan externe tools (zoals de Apollo client of de WordPress Object Cache), wat betekent dat er een extra laag aan de applicatie wordt toegevoegd, de complexiteit ervan wordt verhoogd en het mogelijk trager wordt.

(Deze redenen zullen deels de beslissing hebben geleid om persisted queries native in WPGraphQL te implementeren.)

De Apollo client draait bijvoorbeeld, nou ja, op de client. Als je de website bezoekt vanaf een goedkope mobiele telefoon met weinig power, zal die extra JavaScript-code de prestaties van de applicatie beïnvloeden.

Evenzo kunnen ontwikkelaars die met WordPress werken goed zijn in PHP, maar niet zo goed in JavaScript. Nu hun API's cachen, betekent dat ze zich ook zorgen moeten maken over de JavaScript-laag.

Gato GraphQL heeft hier slimmer over nagedacht. Omdat het persisted queries biedt, wat betekent dat queries worden uitgevoerd op hun eigen endpoint, maakt het mogelijk om deze endpoint-URL's te cachen via HTTP caching.

De HTTP caching-header heeft de max-age-waarde automatisch berekend op basis van alle max-age-waarden voor alle velden in de query, en deze informatie is geconfigureerd via de WordPress-editor, op een veld-voor-veld basis.

Als gevolg hiervan kan de API worden gecached over meerdere lagen (in de client, CDN en server), en wordt het native afgehandeld binnen de plugin, zonder de noodzaak om een andere laag toe te voegen.

Bekijk deze video die laat zien hoe API-endpoints worden gecached:

Winnaar van de ronde: Gato GraphQL.

Round 9: Integratie met Gutenberg

Het was zo dat Gutenberg de toekomst van WordPress zou zijn. Dat is niet meer zo: Gutenberg is nu het heden van WordPress (dus we kunnen het de WordPress-editor noemen), en Full Site Editing is de nieuwe toekomst geworden.

Uiteraard moeten onze API's goed geïntegreerd zijn met de WordPress-editor. Dit betekent niet alleen het ophalen en plaatsen van gegevens voor blokken, maar ook het mogelijk aandrijven van functies in de WordPress-editor zelf.

Omdat GraphQL-subscriptions de server in staat stellen om gegevens in realtime naar de client te pushen, zou het bijvoorbeeld geschikt zijn voor het aandrijven van de gezamenlijk bewerken- en meldingen-functies.

WPGraphQL kan blokgegevens opvragen via de WPGraphQL Gutenberg-extensie. Deze extensie maakt een nieuw type aan voor elk blok, zodat we CoreParagraphBlock, CoreQuoteBlock, enz. hebben.

Gato GraphQL zal binnenkort blokgegevens kunnen opvragen (dit is nog in ontwikkeling). In plaats van een nieuw type per blok te maken, heeft het echter één enkel Block-type om alle blokken te vertegenwoordigen, en dan kunnen we de specifieke metadata voor een blok extraheren op basis van de naam ervan.

Kijk bijvoorbeeld hoe je de inhoud in een alineablok kunt vertalen (met behulp van de @strTranslate-directive, die verbinding maakt met de Google Translate API):

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")
  }
}

Winnaar van de ronde: gelijkspel.


De reikwijdte verbreden

"Ik heb een droom."

Gutenberg-blokken zijn bedacht als één enkele interface voor het aanmaken van inhoud in WordPress, waarmee de ontwikkeling van de code voor het CMS aanzienlijk wordt vereenvoudigd en de kennis die van gebruikers wordt vereist wordt verminderd.

Hoewel ze zijn geïntroduceerd voor het aanmaken van inhoud, nemen blokken gestaag alle andere gebieden van het CMS over, waaronder widgets, menu's en binnenkort thema's via Full Site Editing. En in de toekomst zullen ze ook meertalige mogelijkheden en gezamenlijk bewerken ondersteunen (functies die we misschien niet eens denken aan als we aan blokken denken), en wie weet wat nog meer.

We kunnen op dezelfde manier over GraphQL denken: als één enkele interface voor interactie met gegevens. Dat betekent niet alleen het ophalen en plaatsen van gegevens, maar elke interactie die gegevens omvat, inclusief bewerken.

WordPress heeft een unieke kans om echt het OS van het web te worden: een systeem aangedreven door Gutenberg, waarmee de gebruiker elk type inhoud kan invoeren (tekst, afbeeldingen, video, audio, enz.), verwerken via zijn eigen tools of een cloudgebaseerde dienst, en publiceren naar de uiteindelijke bestemming, of dat nu de WordPress-site is of ergens anders.

Maar achter deze krachtige droom moet een echt krachtige API staan, om aan elke vereiste te voldoen die we eraan stellen. Een API die gebaseerd kan zijn op GraphQL, maar die is ontworpen om ook zijn beperkingen te overstijgen.

Round 10: Ondersteuning voor aangepaste directives

Begin van ronde 10

WPGraphQL wordt niet geleverd met een enkele directive. Ik zeg niet dat het ze niet ondersteunt (de engine webonyx/graphql-php doet dat wel), maar dat het geen implementatie biedt van een aangepaste directive.

"Nou en?" denk je misschien. "Waarvoor hebben we directives nodig? Als iemand het resultaat van de query wil aanpassen, kunnen ze dat aan de clientkant doen!"

Waarom heb ik directives nodig?

Dit is een kwestie van mening, en er is geen goed of fout. Maar laat me je iets vertellen: directives zijn een ongelooflijk nuttige functie, die GraphQL helpt te onderscheiden van REST. Als je ze niet gebruikt, maak je hoogstwaarschijnlijk niet het meeste uit je API.

Directives zijn niet gereguleerd door de spec, zodat GraphQL-servers ze op elke gewenste manier kunnen implementeren, ze zo krachtig kunnen maken als nodig. Daarom wordt veel nieuwe functionaliteit in GraphQL eerst geïntroduceerd via directives, zoals @stream en @defer.

Gato GraphQL behandelt directives met respect. Ze worden slechts één keer uitgevoerd met de gegevens van alle entiteiten, voor alle velden waarop ze worden toegepast (wat verklaart waarom de @strTranslate-directive resultaten van de Google Translate API zo snel kan ophalen), en de GraphQL-engine zelf is gebaseerd op een directive pipeline.

Ahhhh, maar je bent bang om al deze kracht beschikbaar te stellen aan de gebruikers, toch? Dat is een geldige zorg. Maar dan kun je gewoon de toegang tot het enkele endpoint verwijderen en toegang tot gegevens alleen bieden via persisted queries, waar jij (de beheerder van de site) de enige persoon bent met toegang tot de directives.

Dus ofwel je profiteert ervan, of er gebeurt niets.

Als je van directives houdt, geweldig — je zult van Gato GraphQL houden! ❤️

Maar aan de andere kant, als je er niet van houdt, gebeurt er niets.

Winnaar van de ronde: Gato GraphQL.

(Als je denkt dat "we geen stinkende directives nodig hebben", wees dan alsjeblieft niet boos op mij... Ik doe gewoon mijn werk.)

Round 11: Ondersteuning voor REST

"Ahhhhh? REST? Welke REST? Hebben we het hier niet over GraphQL? Waarom praat je over REST? Waarom wil je mijn leven ingewikkelder maken?"

Meer dan dit kan ik niet voor je doen

Ja, op het eerste gezicht lijkt dit onderwerp misplaatst. Maar ik heb het om een zeer eenvoudige reden toegevoegd aan deze vergelijking: Matt Mullenweg heeft gezegd dat hij GraphQL onderzoekt voor mogelijke opname in WordPress core, en het enige waar bijdragers zich zorgen over zullen maken is dat ze twee codebases moeten onderhouden.

Wat leidt tot de voor de hand liggende vraag: kan de GraphQL-server ook REST afhandelen?

Het antwoord is "gedeeltelijk ja" voor WPGraphQL, en "volledig ja" voor Gato GraphQL.

Wat WPGraphQL betreft. Het is mogelijk om een REST-endpoint te definiëren dat, wanneer het wordt opgelost, eenvoudig een GraphQL-query uitvoert die de vereiste velden bevat, hetzij als een interne aanroep van de GraphQL-engine, of als een externe POST-bewerking uitgevoerd op dezelfde webserver.

Maar dat is niet genoeg om de WP REST API te voldoen, omdat het ook een JSON-schema heeft, en we kunnen er niet zonder.

Wat Gato GraphQL betreft. Ik moet toegeven dat ik geluk heb gehad, want het werk aan de onderliggende engine (het serverside componentmodel genaamd PoP) begon rond 2013, dat wil zeggen enkele jaren voordat ik wist van iets dat GraphQL heette, en dit project evolueerde met zijn eigen ideeën (die ik heb gedocumenteerd in dit vintage artikel van mij).

Vervolgens, toen ik ongeveer 1,5 jaar geleden begon met het coderen van de CMS-agnostische GraphQL-server (waarop Gato GraphQL is gebaseerd), heb ik de ideeën die voor PoP zijn ontwikkeld samengevoegd met de fundamenten die GraphQL heeft gelegd, waardoor een systeem is ontstaan dat de GraphQL-spec in zijn geheel ondersteunt, terwijl het ook een andere set functies kan toevoegen.

In dit opzicht is het schema dat PoP gebruikt API-agnostisch en is het een superset van dat van GraphQL. Het PoP-schema is beschikbaar op /api/graphql/?query=fullSchema.

Vervolgens formatteert de GraphQL-serverlaag het PoP-schema volgens de GraphQL-specificatie, wat het GraphQL-schema oplevert. En op dezelfde manier kunnen we het JSON-schema genereren dat vereist is door de WP REST API.

Het genereren van dit JSON-schema is nog niet gedaan, maar het is haalbaar.

Wat al wel is gedaan, is het produceren van het antwoord van de query in meerdere formaten. Bijvoorbeeld, deze GraphQL-query:

{
  posts {
    id
    title
    date
    author {
      name
    }
  }
}

Wordt ook opgelost via dit REST-endpoint: /posts/api/rest/?query=id|title|date|author.name.

En we hoeven daar niet te stoppen. Moet je resultaten produceren met nog een ander formaat, zoals XML? Geen probleem: /api/?query=posts.id|title|date|author.name&datastructure=xml.

(Dit zou kunnen helpen bij het implementeren van het voorstel voor een nieuw import/exporttool voor WordPress, gebaseerd op een schema. Dit maakt ook iets meer duidelijk wat ik eerder zei: één enkele interface kan alle data-interacties aandrijven, zowel binnen het CMS als van het CMS met externe API's.)

Winnaar van de ronde: Gato GraphQL.

Round 12: Ondersteuning voor nieuwe functies

Is de GraphQL-specificatie definitief? Het antwoord is nee: de spec evolueert voortdurend. Op dit moment zijn er 100 open issues, waarvan er veel voorstellen bevatten die in de toekomst zullen worden geformaliseerd.

Nu zullen er onder die 100 issues zeker nieuwe functies zijn waar we vandaag al van kunnen profiteren, toch? Zo ja, waarom dan wachten?

Dat is precies mijn manier van denken.

We kunnen niet eeuwig wachten

"Maar als iets niet in de GraphQL-spec staat, dan moeten we het niet toevoegen aan de GraphQL-server, anders raken gebruikers in de war!"

Goed punt. Maar als we de nieuwe functies alleen beschikbaar stellen als opt-in, zullen gebruikers er noodzakelijkerwijs van op de hoogte zijn en zal er geen probleem of misverstand ontstaan.

Nogmaals, dat is mijn manier van denken. Dit is echter een kwestie van mening, dus als je liever alleen functies gebruikt die elke GraphQL-server ondersteunt, is dat prima.

Ik geloof dat dit is hoe WPGraphQL werkt. In ieder geval heb ik geen enkele functie gezien die verder gaat dan wat is goedgekeurd in de spec.

Voor Gato GraphQL scan ik echter regelmatig de lijst met issues in de spec en als ik een coole functie vind die mijn server zonder veel moeite kan ondersteunen, implementeer ik die. (Dit is eigenlijk een van mijn hobby's.)

Dit zijn de "vooruitkijkende" functies die ik tot nu toe heb geïmplementeerd:

Meervoudige query-uitvoering
Schema-naamruimte
Geneste mutaties
Samengestelbare directives
Proactieve feedback
Op velden en directives gebaseerde versiebeheer

En ik ben al van plan toe te voegen:

✳️ Subscriptions (dit maakt al deel uit van de spec)
✳️ @stream- en @defer-directives
✳️ Platte ketensyntaxis

Winnaar van de ronde: Gato GraphQL.


Oordeel!

Dames, heren.

Het is tijd voor het oordeel

Wat een onvergetelijke avond! Wat een wedstrijd die we zojuist hebben meegemaakt! Twee zware zwaargewichten die het beste van zichzelf geven voor hun droom.

Een droom die ze allebei najagen, maar die slechts één van hen kan grijpen.

En nu zullen we weten wie dat is. Nu is het tijd voor de waarheid!

Wie zal de wereldkampioen "GraphQL in WordPress" zijn?

Is het de alom geprezen, geliefd door de massa's, vermeld in grote publicaties, huidige kampioen, WPGraphQL?

Of is het de oneerbiedigde, die-op-je-tenen-trapt-zonder-excuses-te-vragen, komt-onaangekondigd-op-het-feest uitdager, Gato GraphQL?

De deelnemers wachten op het oordeel

We wachten op het oordeel van de rechter. Wat een spanning! O Heilige Maria, laat mijn hart dit moment weerstaan!

🥁 En 🥁 de 🥁 winnaar 🥁 isssssssssssss 🥁 ...

Het is gelijkspel!

De 2 vechters, de 2 zwaargewichten, het is gelijkspel!

De deelnemers omhelzen elkaar

Wat een prachtig moment! De twee deelnemers omhelzen elkaar, laat zien dat we allemaal vrienden zijn in de WordPress-gemeenschap, als één grote familie.

Dus wat is de rechtvaardiging voor het gelijkspel? De rechter legt uit:

👑 WPGraphQL is de meer populaire, en het gebruik ervan is wijdverspreider.

👑 Gato GraphQL heeft een betere architectuur en zou WordPress op de lange termijn potentieel beter kunnen dienen.

Dames en heren, u heeft het oordeel van de rechter gehoord!

En onze trofee heeft twee handschoenen: één voor elke deelnemer.

De trofee 'GraphQL in WordPress'

Maar wat is jouw oordeel?

Blijf je WPGraphQL onvoorwaardelijk gebruiken voor je headless-behoeften?

Of geef je Gato GraphQL de kans die het opeist, download de plugin, en probeer je het uit?


Dames en heren. Dit is alles voor de avond.

We hopen oprecht dat je van de wedstrijd hebt genoten.

En laten we hopen dat we binnenkort een nieuwe ontmoeting hebben tussen onze twee kampioenen.

Goedenacht.

Update 01/05/2024: Lees meer in de vergelijking Gato GraphQL vs WPGraphQL.


Abonneer je op onze nieuwsbrief

Blijf op de hoogte van alle updates over Gato GraphQL.