Blog

🥊 Gato GraphQL vs WPGraphQL: der Kampf!

Leonardo Losoviz
Von Leonardo Losoviz ·

Update 01/05/2024: Schau dir den Vergleich Gato GraphQL vs WPGraphQL an.

Meineeeeeeeeeee Damen und Herren.

Ankündigung des bevorstehenden Kampfs

Willkommen in der MGM Grand Garden Arena zum Kampf des Jahrhunderts! Heute Abend schreiben wir Geschichte. Zwei junge Kämpfer werden sich im Ring gegenüberstehen und um den Preis kämpfen, für den sie so hart gearbeitet haben:

Den Weltmeistertitel in "GraphQL in WordPress" zu gewinnen 🏆

Zu unserer Rechten haben wir den amtierenden Champion. Obwohl erst 4 Jahre alt, ist er bereits voller Erfahrung, hat kürzlich Version 1.0 erreicht und wurde im wp.org-Verzeichnis veröffentlicht, und er ist sehr beliebt bei der Menge.

🥁 Gebt 🥁 ihm 🥁 einen 🥁 herzlichen 🥁 Empfang 🥁 ...... WPGraphQL!

Der amtierende Champion, WPGraphQL

Zu unserer Linken haben wir den Herausforderer. Er ist erst seit 1 Monat auf der Welt, aber er ist hochenergetisch und ehrgeizig, zeigt seine Stärke vom ersten Tag an. Er war derjenige, der die heutige Begegnung gesucht hat. Heute Abend ist seine Chance, und die Welt schaut zu.

🥁 Gebt 🥁 ihm 🥁 einen 🥁 herzlichen 🥁 Empfang 🥁 ...... Gato GraphQL!

Der Herausforderer, Gato GraphQL

Heute Abend treffen unsere Kontrahenten zum ersten Mal von Angesicht zu Angesicht aufeinander, in einem Kampf über 12 Runden. Während sie ihre Positionen in der Mitte des Rings einnehmen und auf den Eröffnungsgong warten, studieren sie sich gegenseitig und versuchen, die verwundbaren Punkte des anderen zu finden. Dennoch zeigen sie nur Zuversicht.

Die 2 glorreichen Kämpfer studieren sich gegenseitig

Wer wird die Oberhand behalten? Wird WPGraphQL seinen Vorteil behalten, gestützt auf die Unterstützung seiner Anhänger? Oder wird der Neuankömmling Gato GraphQL eine ahnungslose Community von der Kraft seiner Fäuste überzeugen und eine Spur der Begeisterung hinterlassen, die die Menge auf seine Seite zieht?

Heute Abend, meine Damen und Herren, werden wir es herausfinden.

Setzt eure Wetten. Und genießt den Kampf!


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


Mir wurde kürzlich die Frage gestellt, die Unterschiede zwischen meinem Plugin, Gato GraphQL, und WPGraphQL zu erklären.

Beide Plugins sind GraphQL-Server für WordPress und dienen damit demselben Zweck. Unter der Haube haben sie jedoch unterschiedliche Eigenschaften, die das eine besser als das andere machen können, wenn es darum geht, ein bestimmtes Verhalten zu erfüllen.

Auch wenn ich zu meinem eigenen Plugin voreingenommen bin, habe ich versucht, einen fairen Vergleich zu ziehen, basierend auf Themen, die ich sowohl für GraphQL als auch für WordPress als wichtig erachte. (Wenn Leser einen Vergleich zu einem anderen Thema wünschen, werde ich dem gerne nachkommen.)

Der Vergleich ist nicht erschöpfend. Zum Beispiel würde ich auch gerne einige Benchmarks durchführen und die Geschwindigkeit der Auflösung derselben GraphQL-Anfrage mit beiden Servern messen. (Wenn Leser diesen Vorschlag attraktiv finden, kann ich das für einen kommenden Artikel tun.)

Ich habe meinen Vergleich in 4 Hauptbereiche aufgeteilt: Popularität, Codestil und Standards, Dringende Angelegenheiten und Erweiterung des Rahmens, mit je 3 Punkten, also insgesamt 12 "Runden". Am Ende geben die Richter ihr Urteil ab, um den Champion zu benennen.

Klicke unten, um direkt zu einem Thema zu springen:

🔔 Ding 🔔 ding 🔔 diiiiiing...

Der Eröffnungsgong hat geläutet...

Der Kampf hat begonnen!


Popularität

Jede Software (oder Technologie) muss von Menschen genutzt werden, sonst ist ihre Überlegenheit gegenüber den Alternativen nur eine Anekdote.

Zum Beispiel verwenden wir immer noch hauptsächlich die QWERTY-Tastatur, obwohl es Alternativen gibt, die schnelleres Tippen ermöglichen.

Wie beliebt sind die beiden Plugins?

Runde 1: Wer nutzt es, und wie vollständig ist es

WPGraphQL war bisher ein Synonym für GraphQL in WordPress. In den über 4 Jahren seiner Entwicklung (beginnend im November 2016) hat es über 2,8k Sterne im Repository gesammelt, eine Community von über 4600 Followern und fast 100 Mitwirkende am Projekt.

Es hat Version 1.0 erreicht und wurde im November 2020 ins Plugin-Verzeichnis auf wp.org hochgeladen. Seitdem hat es über 8000 aktive Installationen gesammelt. Es ist derzeit die einzige Lösung für das Beziehen von WordPress-Inhalten nach Gatsby und, jüngst, haben mehrere Projekte es in ihre Stacks aufgenommen, darunter WPEngines Headless-Framework und WebDevStudios' Next.js-WordPress-Starter.

Mit anderen Worten: WPGraphQL ist beliebt.

Die Entwicklung von Gato GraphQL begann ernsthaft vor etwa 1,5 Jahren (als Teil eines größeren Projekts) und erreichte vor 6 Monaten einen "gut genug"-Status, woraufhin es 150 Sterne im Repository erhielt. Das Plugin befindet sich derzeit bei Version 0.7 und ist noch einige Monate davon entfernt, Version 1.0 zu erreichen (zum Beispiel fehlen noch Kategorien im Schema).

Letzten Monat habe ich die aktuelle Website gatographql.com gestartet, und seitdem habe ich das Plugin über den Blog beworben (wie den Artikel, den du gerade liest), und auch einen Einführungsartikel auf CSS-Tricks veröffentlicht. Diese Bemühungen haben mehrere hundert Menschen auf die Website gebracht, und über 100 Besucher haben das Plugin heruntergeladen.

Mit anderen Worten: Gato GraphQL wird langsam aber stetig populär und ist ein Work in Progress.

Gewinner der Runde: WPGraphQL.

Ein Treffer! WPGraphQLs Schlag erreicht Gato GraphQL

Runde 2: Verfügbarkeit von Erweiterungen

Erweiterungen ermöglichen die Interaktion mit anderen Plugins über Gato GraphQL.

WPGraphQL verfügt über Erweiterungen für ACF, WooCommerce, Yoast und einige andere.

Gato GraphQL hat noch keine Erweiterungen, und ich erwarte nicht, dass es vor der Veröffentlichung von Version 1.0 viele geben wird.

Gato GraphQL legt in seiner Architektur jedoch großen Wert auf Erweiterungen und ermöglicht es dem Benutzer, diese (aktivieren, deaktivieren, konfigurieren und deren Dokumentation lesen) von einem zentralen Ort aus zu verwalten, der Seite "Modules":

Modules-Seite in Gato GraphQL

Mit anderen Worten: Während WPGraphQL bereits Erweiterungen hat, bereitet Gato GraphQL das Feld dafür vor.

Gewinner der Runde: WPGraphQL.

WPGraphQL trifft erneut!

Runde 3: Zielgruppe

WPGraphQL richtet sich an Entwickler: Wenn du Daten von deiner WordPress-Website abrufen möchtest, musst du deine GraphQL-Anfrage irgendwo in deinem Code speichern (höchstwahrscheinlich in einer JavaScript-Funktion). Um sie dann nutzen zu können, musst du gut genug programmieren können.

Gato GraphQL hingegen folgt der WordPress-Philosophie, dass jeder es nutzen können sollte, einschließlich Nicht-Technikern. Um dieses Ziel zu erreichen, ermöglicht es, eine GraphQL-Anfrage über den WordPress-Editor zu erstellen und zu verwalten, sodass das Zugänglichmachen der Daten einer WordPress-Website über eine API so einfach ist wie das Erstellen eines Blogbeitrags.

Darüber hinaus legt Gato GraphQL mehr Wert darauf, Clients für die visuelle Interaktion mit dem GraphQL-Dienst anzubieten. Während beide Plugins den GraphiQL-Client zur Ausführung von Anfragen bereitstellen, bietet nur Gato GraphQL auch den Voyager-Client zur interaktiven Erkundung des Schemas:

Visualisierung des GraphQL-Schemas

Gewinner der Runde: Gato GraphQL.

Gato GraphQL liefert einen guten linken Haken!


Codestil und Standards

Lass uns über Code sprechen!

Wenn du GraphQL verwendest, machst du wahrscheinlich Headless WordPress und renderst die Website mit einem JavaScript-Framework, was ein modernes Paradigma ist. Außerdem mag WordPress ein altes CMS sein, aber GraphQL ist eine moderne Schnittstelle für den Zugriff auf Daten der Website. Daher kann ich sicher davon ausgehen, dass du ein kluger Entwickler bist, der eleganten Code schreiben möchte, und keine suboptimale Lösung akzeptieren wirst.

Wie elegant ist der Code (aus ihrer eigenen Codebase und der von unseren eigenen Implementierungen erwartete) dieser beiden Plugins?

Runde 4: PHP-Anforderungen

Sowohl WPGraphQL als auch Gato GraphQL erfordern PHP 7.1+.

Es gibt jedoch einen Unterschied: Gato GraphQL ist eigentlich mit PHP 7.4 kodiert und wird dann für die Produktion auf PHP 7.1 transpiliert.

Daher ist die Entwicklung von Gato GraphQL viel angenehmer: Du kannst neuere PHP-Funktionen verwenden, einschließlich des object-Typs, typisierter Eigenschaften und Arrow-Functions. Und sobald die Unterstützung für PHP 8.0 hinzugefügt wird (was passiert, wenn die neue Version von Lando veröffentlicht wird), kannst du auch Union-Types, den match-Ausdruck und weitere verwenden.

Gewinner der Runde: Gato GraphQL.

Gato GraphQL hinterlässt seine Spuren!

Runde 5: Codierungspraktiken

Beginnen wir mit WPGraphQL. Wenn wir uns das Repository wp-graphql/wp-graphql ansehen, fällt mir etwas auf:

Der vendor-Ordner im Repository gespeichert

Beim Heranzoomen:

Inhalt des vendor-Ordners

Tut mir leid, aber es gibt nur eine Möglichkeit, wie ich darauf reagieren kann:

Ich kann dir vieles im Leben verzeihen, aber nicht das

Den vendor-Ordner von Composer ins Repository zu committen ist eine schlechte Praxis, und Composer rät ausdrücklich davon ab.

Dieses Problem zu beheben ist nicht schwierig (ich habe sogar eine Methode basierend auf GitHub Actions beschrieben), weshalb ich mich frage, warum es dort ist.

Ich würde sagen, dass WPGraphQL sich in dieser Runde selbst schlägt!

Autsch!

Weiter. Die Entwicklung für WPGraphQL erfordert das Kennen einer sehr umfangreichen Sammlung von Hooks (Actions und Filter). Wenn wir zu WPGraphQLs Entwicklerreferenz gehen, können wir den Umfang davon erkennen.

Um einen Screenshot der Liste der Actions zu machen, musste ich meinen Browser auf 50% herauszoomen:

Action-Hooks zum Erweitern von WPGraphQL

Für die Liste der Filter habe ich auf 30% herausgezoomt (das Minimum, das Firefox unterstützt), und selbst dann konnte ich nicht die gesamte Liste erfassen:

Filter-Hooks zum Erweitern von WPGraphQL


Wechseln wir zum Repository GatoGraphQL/GatoGraphQL, dem Monorepo, das Gato GraphQL (unter anderen Projekten) enthält.

Dies sind einige der Eigenschaften des Codes:

✅ Konform mit den Standards PSR-1, PSR-4 und PSR-12.

✅ Der gesamte Code ist in mehrere, atomare Pakete aufgeteilt, und alle (über 100 für das Plugin, über 200 für das gesamte Projekt) werden im selben Monorepo gehostet.

✅ Verwendet Composer zur Verwaltung aller Abhängigkeiten.

✅ Verwendet Symfony Dependency Injection zur Verwaltung aller Dienste in der Anwendung. Um einen neuen Type-Resolver, Field-Resolver oder Directive-Resolver zu registrieren, müssen wir einfach einen neuen Dienst im Container registrieren.

✅ Jede Klasse ist ein Dienst, und Symfony Dependency Injection kümmert sich um das automatische Zusammenfügen der gesamten Anwendung.

✅ Der zugrunde liegende GraphQL-Server ist CMS-agnostisch. Gato GraphQL implementiert die Verträge für WordPress und fügt etwas benutzerdefinierte Logik hinzu (zum Beispiel, um die Clients bereitzustellen).

Der WordPress-spezifische Code macht nur etwa 10% des Gesamtcodes aus. Die Replikation dieser 10% für ein anderes Framework oder CMS (Laravel/Drupal/etc) kann eine Implementierung eines GraphQL-Servers für diese bereitstellen.

✅ Als Konsequenz des CMS-agnostischen Ansatzes bedeutet das Kodieren eines Resolvers das Kodieren seiner generischen Geschäftslogik, unterstützt von wiederverwendbaren Diensten. Wir denken nie in Begriffen von WordPress-Code und müssen uns selten mit dessen technischen Schulden befassen.

✅ Ebenso ist das GraphQL-Schema kein 1:1-Abbild des WordPress-Datenmodells, was die technischen Schulden, die WordPress auf der Datenschicht angesammelt hat, umgeht und eine saubere Schnittstelle bietet.

✅ Das N+1-Problem von GraphQL kann nicht auftreten, durch architektonisches Design, ohne den Entwickler überhaupt zu belasten.

✅ Der Server ist nicht nur ein GraphQL-Server: Er ist eigentlich ein API-Server, bei dem die Antwort in anderen Formaten oder Spezifikationen (z.B.: REST) aus einer einzigen Quelle der Wahrheit ausgegeben werden kann. (Mehr dazu in Runde 11).

✅ Es wird kein vendor-Verzeichnis committet. Stattdessen wird der Quellcode in Distributionscode umgewandelt (d.h. das fertige Plugin zur Installation auf der WordPress-Website) über GitHub Actions und in ein dist-Repository deployt, wo er tatsächlich den vendor-Ordner enthält.

✅ Bei der Generierung des Codes für die Distribution wird er mit PHP-Scoper gescoped, und der Quellcode, der PHP-7.4-Code enthält, wird auf PHP 7.1 transpiliert.

✅ Da das Scoping-Problem gelöst ist, kann das Plugin auf jede Drittanbieter-Abhängigkeit zurückgreifen. Derzeit nutzt es Symfonys DependencyInjection, Cache und Dotenv, Guzzle (zur Interaktion mit externen APIs), die Pipeline der League und einige andere.

Dies ist nicht nur für die Gegenwart, sondern auch für die Zukunft wichtig: Ich kann sicher sein, dass ich jede Abhängigkeit aus dem Packagist-Repository verwenden kann, sodass ich das Rad nicht neu erfinden muss.

Felder werden Typen zugeordnet, was das GraphQL-Schema leicht erweiterbar macht.

Gewinner der Runde: Gato GraphQL (mit großem Abstand, wage ich zu sagen, wenn du nichts dagegen hast).

Nach einer harten Runde braucht WPGraphQL etwas Erholung

Runde 6: Schema erweitern

Fügen wir ein Feld zum GraphQL-Schema hinzu.

Wir folgen dem Tutorial für WPGraphQL. Der vorgeschlagene Code ist der folgende. Er deklariert einen Action-Hook zur Ausführung einer Funktion, die ein Array deklariert. Sowohl die Beschreibung der Felder als auch ihre Auflösung werden innerhalb des Arrays bereitgestellt:

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

Dieses Beispiel ist so einfach wie möglich: Der Resolver macht praktisch nichts. Dennoch fällt es mir schon schwer, den Code anzuschauen und sofort zu verstehen, was er tut. Nein, ich bin nicht sarkastisch: Alle Farben dieses Codes in meinem Editor kämpfen um meine Aufmerksamkeit. Außerdem gibt es keine Trennung der Verantwortlichkeiten, und der Code scheint nicht sehr wiederverwendbar zu sein.

Daher liegt es am Entwickler (also an dir), den Code während der Entwicklung der Anwendung lesbar, wiederverwendbar, fehlerfrei und vieles mehr zu machen; die Bibliothek selbst scheint dabei wenig zu helfen.

Ich nenne diesen Stil "ADD": Array-Driven Development. Ich kann nicht behaupten, ein Fan davon zu sein.

(Um fair gegenüber WPGraphQL zu sein: Dies ist eine Standard-Codierungspraxis und auch diejenige, die vom zugrunde liegenden Engine webonyx/graphql-php verwendet wird.)


In Gato GraphQL ist der gesamte Code SOLID. Um ein Feld im GraphQL-Schema zu registrieren, erstellen wir eine Klasse, die das Interface FieldResolverInterface implementiert (eigentlich erweiternd von AbstractSchemaFieldResolver, das bereits viele Methoden implementiert hat), und wir registrieren sie im Container.

Zum Beispiel stellt dieser Code die Felder username, email und url für den Typ User bereit:

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;
  }
}

Ich glaube, dass meine Lösung eleganter ist als die von WPGraphQL. Das ist jedoch Geschmackssache. Ich weiß, dass viele Entwickler Array-Driven Development nichts ausmacht und es sogar bevorzugen, da sie in einem kompakten Code-Block die gesamte Logik implementieren können.

Gewinner der Runde: Unentschieden.

Unentschieden


Pause

Was für eine Nacht, meine Damen und Herren.

Zeit, den bisherigen Kampfverlauf zu analysieren

Wir haben die Mitte des Kampfes erreicht, also ist jetzt ein guter Zeitpunkt für eine Toilettenpause und für einige Kommentare zu dem, was wir bisher erlebt haben.

(In der Zwischenzeit sollte ich eine Werbung von meinen Sponsoren zeigen. Leider habe ich noch keine. Wenn dein Unternehmen die Entwicklung von Gato GraphQL finanzieren und Aufmerksamkeit bei Prime Media wie diesem Event erhalten möchte, schreib mir eine Nachricht.)

Sponsor mich, um Zugang zu erstklassiger Werbung für deine Marke zu erhalten

Was für ein Kampf! WPGraphQL war anfangs Feuer und Flamme! Er startete den Kampf in großartiger Form und versetzte Gato GraphQL schrecklich mächtige Schläge, der kaum auf den Beinen stehen konnte. Schlag nach Schlag nach Schlag. Ich wäre nicht gerne in Gato GraphQLs Haut gewesen.

Ich muss zugeben, ich dachte nach den ersten 2 Runden, der Kampf würde bald vorbei sein. Ich erwartete jederzeit den Knockout. Ein winkendes Handtuch, das um Gnade bat. Aber Gato GraphQL widerstand. Das muss man ihm lassen. Was für eine unerschütterliche Entschlossenheit, wirklich bemerkenswert!

Und dann geschah die Verwandlung. Irgendwo ab der 3. Runde schien Gato GraphQL aus dem Nichts Energie zu schöpfen und begann nicht nur, sich zu verteidigen, sondern auch Schläge zurückzugeben, von denen viele WPGraphQLs Gesicht trafen. Ich sah WPGraphQL zittern und wanken! So etwas hatten wir von unserem amtierenden Weltmeister noch nie gesehen. Was für eine wirklich bemerkenswerte Verwandlung!

Und dann, nachdem er das Selbstvertrauen seines Gegners erschüttert hatte, übernahm Gato GraphQL ab der 4. Runde die Initiative und teilte eine Reihe letaler Schläge aus. Das war erstaunlich! Zum Glück steht ihm unser Weltmeister WPGraphQL gegenüber, der die Schläge aushalten konnte, aufgerieben durch den Jubel und das Mitgefühl der Menge. Was für ein Held! Jeder andere wäre sofort zusammengebrochen, aber nicht er, er ertrug die Schläge wie der Champion, der er ist.

Aber wird er noch lange Champion sein? Noch wurde niemand ausgeknockt, noch hat niemand das Handtuch geworfen. Der Kampf könnte jederzeit eine entscheidende Wende nehmen. Die beiden Kämpfer wissen, was sie wollen, und ich bin sicher, dass sie wieder mit aller Kraft und all ihrer Entschlossenheit auf ihren Gegner losgehen werden, um zu siegen.

Was für ein Kampf!

Und jetzt, meine Damen und Herren, kommen die beiden Kämpfer zurück in den Ring.

Die Kontrahenten kommen zurück in den Ring

Weiter mit dem Rest des Kampfes!


Dringende Angelegenheiten

Der GraphQL-Server muss vielen Überlegungen Rechnung tragen, nur um den Satz "Hol die Daten, die du brauchst, nicht mehr und nicht weniger" zu erfüllen.

Zum Beispiel:

  • Wie sicher ist er? Wie stellen wir sicher, dass wir keine privaten Daten auf einem öffentlichen Endpoint preisgeben?
  • Wie performant ist er? Wie können wir die Last auf dem Server reduzieren, wenn wir immer wieder dieselbe Anfrage senden, und ihn dabei so schnell wie möglich machen?
  • Wie einfach ist er? Wie gut ist er in WordPress integriert, um die vom CMS bereitgestellten Funktionen zu nutzen?

Und viele weitere Fragen. Das ist nur eine kleine Auswahl, die ich getroffen habe und die ich in den folgenden 3 Runden behandeln werde.

Runde 7: Persisted queries

Persisted queries kombinieren das Beste aus GraphQL und REST: Sie werden mit GraphQL erstellt, sodass es kein Under-/Overfetching von Daten gibt, aber sie werden auf dem Server als Endpoint mit eigenem URL veröffentlicht.

Persisted queries bieten diese Vorteile:

✅ Es ist sicher: Anstatt über den einzigen Endpoint Zugriff auf beliebige Daten zu gewähren, können wir vorab definieren, welche Daten exponiert werden.

✅ Es ist schnell: Da der Zugriff über eine eigene URL erfolgt, kann es auf jeder Schicht zwischen Client und Backend (im Server, CDN, Browser) über Standard-HTTP-Caching gecacht werden.

WPGraphQL bietet Unterstützung für Persisted queries über diese beiden Erweiterungen:

Außerdem hat Jason Bahl (Schöpfer von WPGraphQL) kürzlich angekündigt, dass er in naher Zukunft die Unterstützung für Persisted queries in WPGraphQL hinzufügen wird.

Ich frage mich, was er sich dabei gedacht hat, da es bereits die 2 Erweiterungen gibt. Wie wird es sich von diesen unterscheiden? Vielleicht möchte er es zum Teil des Plugin-Cores machen, um die allgemeinen Sicherheitsmaßnahmen des Plugins zu stärken, ohne von einem Drittanbieter abhängig zu sein?

Oder hat er vielleicht die Implementierung von Gato GraphQL gesehen und möchte eine ähnliche Erfahrung bieten, die über einen visuellen Editor statt über reinen Code bedient wird?

Was uns zu Gato GraphQL bringt. Es bietet nicht nur Persisted queries, sondern hat sich bemüht, sie zu einem zentralen Teil des Angebots zu machen:

✅ Das Plugin ermöglicht das Deaktivieren des einzigen Endpoints, und die Benutzer werden ermutigt, Daten nur über Persisted queries bereitzustellen.

(Im Gegensatz dazu deaktiviert WPGraphQL standardmäßig nur die Introspektion, nicht den eigentlichen Endpoint. Mit anderen Worten können Angreifer immer noch in der Lage sein, auf private Daten zuzugreifen; man macht es ihnen nur schwerer, da sie im Voraus nicht wissen werden, welche privaten Daten vorhanden sind.)

✅ Es ist tief in den WordPress-Editor integriert, sodass das Erstellen einer Persisted query denselben Aufwand erfordert wie das Erstellen eines Blogbeitrags, und jeder es tun kann, nicht nur Programmierer.

✅ Persisted queries sind nicht statisch: Sie können GraphQL-Variablen verwenden, deren Wert über URL-Parameter bei der Ausführung des Endpoints angegeben werden kann.

Schau dir die Erfahrung des Erstellens und Ausführens einer Persisted query in meinem Plugin an:

Gewinner der Runde: Gato GraphQL.

Runde 8: Caching

GraphQL hat einen großen Schwachpunkt: Es ist nicht leicht cachebar. Der Grund ist, dass es vom Senden von POST-Operationen an einen einzigen Endpoint abhängt. Da der einzige Endpoint unterschiedliche Ergebnisse produziert und da die Anfrage im Body der Anfrage statt in URL-Parametern gesendet wird, kann der einzige Endpoint nicht gecacht werden.

Die von vielen GraphQL-Servern angebotene Standardlösung besteht darin, das Caching auf den Client zu verlagern und sich auf Objekt-IDs als Bezeichner der zu cachenden Entität statt auf die URL eines Endpoints zu verlassen. Die beliebteste Bibliothek, die diese Funktionalität bietet, ist der Apollo-Client.

Es gibt eine Diskussion im WPGraphQL-Repository über alle verfügbaren Optionen für das Caching bei WPGraphQL. Interessanterweise sind die meisten davon externe Tools (wie der Apollo-Client oder der WordPress Object Cache), was bedeutet, dass ein zusätzlicher Layer zur Anwendung hinzugefügt wird, die Komplexität erhöht und sie möglicherweise auch langsamer macht.

(Diese Gründe müssen teilweise hinter der Entscheidung stecken, Persisted queries nativ in WPGraphQL zu implementieren.)

Zum Beispiel läuft der Apollo-Client, nun ja, auf dem Client. Wenn du von einem Low-End-Mobiltelefon ohne viel Leistung auf die Website zugreifst, wird dieser zusätzliche JavaScript-Code die Performance der Anwendung beeinträchtigen.

Ebenso können Entwickler, die mit WordPress arbeiten, gut in PHP sein, aber nicht so sehr in JavaScript. Jetzt bedeutet das Cachen ihrer APIs, dass sie sich auch um die JavaScript-Schicht kümmern müssen.

Gato GraphQL war bei diesem Thema klüger. Da es Persisted queries bereitstellt, was bedeutet, dass Anfragen auf ihrem eigenen Endpoint ausgeführt werden, ermöglicht es das Cachen dieser Endpoint-URLs über HTTP-Caching.

Der HTTP-Caching-Header hat den max-age-Wert, der automatisch aus allen max-age-Werten aller Felder in der Anfrage berechnet wird, und diese Information wird über den WordPress-Editor konfiguriert, feldweise.

Infolgedessen kann die API über mehrere Schichten hinweg gecacht werden (im Client, CDN und Server) und wird nativ innerhalb des Plugins verwaltet, ohne dass ein weiterer Layer hinzugefügt werden muss.

Schau dir dieses Video an, das zeigt, wie API-Endpoints gecacht werden:

Gewinner der Runde: Gato GraphQL.

Runde 9: Integration mit Gutenberg

Es hieß einmal, Gutenberg sei die Zukunft von WordPress. Nicht mehr: Gutenberg ist jetzt die Gegenwart von WordPress (wir können es also als WordPress-Editor bezeichnen), und Full Site Editing ist die neue Zukunft geworden.

Selbstverständlich müssen unsere APIs eine gute Integration mit dem WordPress-Editor haben. Das bedeutet nicht nur das Abrufen und Posten von Daten für Blöcke, sondern auch das potenzielle Antreiben von Funktionen im WordPress-Editor selbst.

Da GraphQL-Subscriptions den Server beispielsweise dazu bringen können, Daten in Echtzeit an den Client zu pushen, würden sie sich für die Bereitstellung der Funktionen kollaboratives Editieren und Benachrichtigungen eignen.

WPGraphQL kann Block-Daten über die Erweiterung WPGraphQL Gutenberg abfragen. Diese Erweiterung erstellt einen neuen Typ für jeden Block, sodass wir CoreParagraphBlock, CoreQuoteBlock usw. haben.

Gato GraphQL wird bald in der Lage sein, Block-Daten abzufragen (es ist ein Work in Progress). Anstatt jedoch einen neuen Typ pro Block zu erstellen, wird es einen einzigen Typ Block haben, um alle Blöcke darzustellen, und dann können wir die spezifischen Metadaten für einen Block basierend auf seinem Namen extrahieren.

Schau dir zum Beispiel an, wie du den Inhalt innerhalb eines Absatz-Blocks übersetzen kannst (mit der Direktive @strTranslate, die sich mit der Google Translate API verbindet):

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

Gewinner der Runde: Unentschieden.


Erweiterung des Rahmens

"Ich habe einen Traum."

Gutenberg-Blöcke wurden konzipiert, um eine einzige Schnittstelle für das Erstellen von Inhalten in WordPress bereitzustellen, die Entwicklung des Codes für das CMS erheblich zu vereinfachen und den von den Benutzern erforderlichen Lernaufwand zu reduzieren.

Obwohl sie für die Inhaltserstellung eingeführt wurden, übernehmen Blöcke stetig alle anderen Bereiche des CMS, einschließlich Widgets, Menüs und bald auch Themes über Full Site Editing. Und in Zukunft werden sie auch mehrsprachige Funktionen und kollaboratives Editieren unterstützen (Funktionen, an die wir beim Denken an Blöcke vielleicht gar nicht denken), und wer weiß was sonst noch.

Wir können GraphQL in denselben Begriffen denken: als einzige Schnittstelle für die Interaktion mit Daten. Das bedeutet nicht nur das Abrufen und Posten von Daten, sondern jede Interaktion, die Daten beinhaltet, einschließlich Editierung.

WordPress hat eine einzigartige Chance, wirklich zum OS des Webs zu werden: ein System, das von Gutenberg angetrieben wird, das dem Benutzer ermöglicht, jeden Inhaltstyp einzugeben (Text, Bilder, Videos, Audio usw.), ihn über eigene Tools oder einen Cloud-basierten Dienst zu verarbeiten und ihn an sein endgültiges Ziel zu veröffentlichen, sei es die WordPress-Website oder woanders.

Aber hinter diesem mächtigen Traum muss eine wirklich mächtige API stehen, um jeden Anforderung zu erfüllen, den wir an sie stellen. Eine API, die auf GraphQL basieren könnte, aber die auch so konzipiert wurde, um seine Einschränkungen zu überwinden.

Runde 10: Unterstützung für benutzerdefinierte Direktiven

Beginn von Runde 10

WPGraphQL wird ohne eine einzige Direktive ausgeliefert. Ich sage nicht, dass es sie nicht unterstützt (sein Engine webonyx/graphql-php tut es), sondern dass es keine Implementierung einer benutzerdefinierten Direktive anbietet.

"Na und?" denkst du vielleicht. "Wozu brauchen wir Direktiven? Wenn jemand das Ergebnis der Anfrage ändern muss, kann er das auf seinem eigenen Client tun!"

Wozu brauche ich Direktiven?

Das ist Ansichtssache, und es gibt kein Richtig oder Falsch. Aber lass mich dir etwas sagen: Direktiven sind eine unglaublich nützliche Funktion, eine, die dazu beiträgt, GraphQL von REST zu unterscheiden. Wenn du sie nicht verwendest, nutzt du deine API höchstwahrscheinlich nicht optimal aus.

Direktiven sind durch die Spezifikation nicht reguliert, sodass GraphQL-Server sie nach Belieben implementieren und so leistungsfähig gestalten können, wie sie es benötigen. Deshalb wird viel neue Funktionalität in GraphQL zuerst über Direktiven eingeführt, wie @stream und @defer.

Gato GraphQL behandelt Direktiven mit Ehrerbietung. Sie werden nur einmal ausgeführt mit den Daten aller Entitäten, für alle Felder, auf die sie angewendet werden (was erklärt, warum die Direktive @strTranslate Ergebnisse von der Google Translate API so schnell abrufen kann), und der GraphQL-Engine selbst basiert auf einer Direktiven-Pipeline.

Ahhhh, aber du hast Angst, all diese Macht den Benutzern zugänglich zu machen, richtig? Das ist eine berechtigte Sorge. Aber dann kannst du einfach den Zugriff auf den einzigen Endpoint entfernen und Datenzugriff nur über Persisted queries gewähren, wobei du (der Administrator der Website) die einzige Person bist, die Zugriff auf die Direktiven hat.

Also entweder profitierst du, oder es passiert nichts.

Wenn du Direktiven liebst, toll, du wirst Gato GraphQL lieben! ❤️

Aber auf der anderen Seite, wenn es dir nicht gefällt, passiert nichts.

Gewinner der Runde: Gato GraphQL.

(Wenn du glaubst, dass "wir keine stinkenden Direktiven brauchen", bitte sei nicht böse auf mich... Ich mache nur meinen Job.)

Runde 11: Unterstützung für REST

"Ahhhhh? REST? Was REST? Reden wir hier nicht über GraphQL? Warum redest du dann über REST? Warum willst du mein Leben komplizieren?"

Mehr als das kann ich nicht für dich tun

Ja, auf den ersten Blick scheint dieses Thema fehl am Platz zu sein. Aber ich habe es aus einem sehr einfachen Grund in diesen Vergleich aufgenommen: Matt Mullenweg hat gesagt, dass er GraphQL für eine mögliche Aufnahme in den WordPress-Core prüft, und das Einzige, worüber sich Mitwirkende Sorgen machen werden, ist die Pflege von zwei Codebasen.

Was zur naheliegenden Frage führt: Kann der GraphQL-Server auch REST verarbeiten?

Die Antwort lautet "teilweise ja" für WPGraphQL und "vollständig ja" für Gato GraphQL.

Betreffend WPGraphQL: Es ist möglich, einen REST-Endpoint zu definieren, der bei der Auflösung einfach eine GraphQL-Anfrage mit den erforderlichen Feldern ausführt, entweder als interner Aufruf an die GraphQL-Engine oder als externe POST-Operation gegen denselben Webserver.

Aber das reicht nicht aus, um die WP REST API zu erfüllen, denn sie hat auch ein JSON-Schema, und wir können nicht darauf verzichten.

Betreffend Gato GraphQL: Ich muss zugeben, dass ich Glück hatte, denn die Arbeit an seinem zugrundeliegenden Engine (das serverseitige Komponentenmodell namens PoP) begann um 2013, also einige Jahre bevor ich von etwas namens GraphQL wusste, und dieses Projekt entwickelte sich mit einigen eigenen Ideen (die ich in diesem meinem Vintage-Artikel dokumentiert habe).

Als ich dann vor etwa 1,5 Jahren mit der Codierung des CMS-agnostischen GraphQL-Servers (auf dem Gato GraphQL basiert) begann, verschmolz ich die für PoP entwickelten Ideen mit den von GraphQL etablierten Grundlagen und schuf ein System, das die GraphQL-Spezifikation vollständig unterstützt, während es in der Lage ist, einen anderen Satz von Funktionen hinzuzufügen.

In dieser Hinsicht ist das Schema, das PoP verwendet, API-agnostisch und eine Obermenge des von GraphQL. Das PoP-Schema befindet sich unter /api/graphql/?query=fullSchema.

Dann formatiert der GraphQL-Server-Layer das PoP-Schema gemäß der GraphQL-Spezifikation, was das GraphQL-Schema erzeugt. Und ähnlich können wir das JSON-Schema erstellen, das die WP REST API benötigt.

Die Generierung dieses JSON-Schemas ist noch nicht erfolgt, aber es ist machbar.

Was bereits getan wurde, ist die Ausgabe der Antwort der Anfrage in mehreren Formaten. Zum Beispiel diese GraphQL-Anfrage:

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

Sie wird auch über diesen REST-Endpoint aufgelöst: /posts/api/rest/?query=id|title|date|author.name.

Und wir müssen dabei nicht aufhören. Musst du die Ergebnisse in einem noch anderen Format ausgeben, wie XML? Kein Problem: /api/?query=posts.id|title|date|author.name&datastructure=xml.

(Dies könnte helfen, den Vorschlag für ein neues Import/Export-Tool für WordPress, basierend auf einem Schema, zu implementieren. Das macht auch etwas deutlicher, was ich früher gesagt habe: Eine einzige Schnittstelle kann alle Dateninteraktionen antreiben, sowohl innerhalb des CMS als auch vom CMS mit externen APIs.)

Gewinner der Runde: Gato GraphQL.

Runde 12: Unterstützung für neuartige Funktionen

Ist die GraphQL-Spezifikation endgültig? Die Antwort lautet nein: Die Spezifikation entwickelt sich ständig weiter. Im Moment gibt es 100 offene Issues, von denen viele Vorschläge enthalten, die irgendwann in der Zukunft formalisiert werden.

Nun, unter diesen 100 Issues werden sicherlich neue Funktionen sein, von denen wir heute profitieren können, richtig? Wenn ja, warum warten?

Das ist genau meine Denkweise.

Wir können nicht ewig warten

"Aber wenn etwas nicht in der GraphQL-Spezifikation steht, sollten wir es nicht zum GraphQL-Server hinzufügen, oder die Benutzer werden verwirrt sein!"

Guter Punkt. Wenn wir die neuartigen Funktionen jedoch nur als Opt-in verfügbar machen, werden die Benutzer notwendigerweise davon wissen, und es werden keine Probleme oder Missverständnisse auftreten.

Auch das ist meine Denkweise. Das ist jedoch Ansichtssache, also wenn du lieber nur Funktionen verwenden möchtest, die jeder einzelne GraphQL-Server da draußen ebenfalls verwendet, ist das in Ordnung.

Ich glaube, das ist die Arbeitsweise von WPGraphQL. Zumindest habe ich keine einzige Funktion gesehen, die über das hinausgeht, was in der Spezifikation genehmigt wurde.

Für Gato GraphQL hingegen scanne ich regelmäßig die Liste der Issues in der Spezifikation und, wenn ich eine coole Funktion finde, die mein Server ohne großen Aufwand erfüllen kann, dann implementiere ich sie. (Das ist tatsächlich eines meiner Hobbys.)

Dies sind die "zukunftsorientierten" Funktionen, die ich bisher implementiert habe:

Mehrfache Anfragen-Ausführung
Schema-Namespacing
Verschachtelte Mutations
Zusammensetzbare Direktiven
Proaktives Feedback
Feld- und direktiven-basierte Versionierung

Und ich plane bereits, hinzuzufügen:

✳️ Subscriptions (dies ist bereits Teil der Spezifikation)
✳️ @stream- und @defer-Direktiven
✳️ Flat-Chain-Syntax

Gewinner der Runde: Gato GraphQL.


Urteil!

Meine Damen, meine Herren.

Es ist Zeit für das Urteil

Was für eine unvergessliche Nacht! Was für ein Kampf, den wir gerade erlebt haben! Zwei Schwergewichte, die ihr Bestes für ihren Traum gegeben haben.

Ein Traum, dem beide nachjagen, den aber nur einer von ihnen verwirklichen kann.

Und jetzt werden wir wissen, wer das ist. Jetzt ist es Zeit für die Wahrheit!

Wer wird der Weltmeister in "GraphQL in WordPress" sein?

Wird es der weithin gefeierte, von den Massen geliebte, in großen Publikationen vorgestellte amtierende Champion sein, WPGraphQL?

Oder wird es der respektlose, tritt-dir-auf-die-Füße-ohne-um-Verzeihung-zu-bitten, kommt-uneingeladen-zur-Party-Herausforderer sein, Gato GraphQL?

Die Kontrahenten warten auf das Urteil

Wir warten auf das Urteil des Richters. Was für eine Spannung! Oh Santa Maria, lass mein Herz diesen Moment widerstehen!

🥁 Und 🥁 der 🥁 Gewinner 🥁 iiiiissssssssssssst 🥁 ...

Es ist ein Unentschieden!

Die 2 Kämpfer, die 2 Schwergewichte, sie trennen sich unentschieden!

Die Kontrahenten umarmen sich

Was für ein wunderbarer Moment! Die beiden Kontrahenten umarmen sich und zeigen, dass wir alle Freunde in der WordPress-Community sind, wie eine große Familie, die wir sind.

Also, was ist die Begründung für das Unentschieden? Der Richter erklärt:

👑 WPGraphQL ist das populärere, und seine Nutzung ist weiter verbreitet.

👑 Gato GraphQL hat eine bessere Architektur und könnte WordPress langfristig potenziell besser dienen.

Meine Damen und Herren, ihr habt das Urteil des Richters gehört!

Und unser Pokal hat zwei Handschuhe: einen für jeden Kontrahenten.

Der 'GraphQL in WordPress'-Pokal

Aber was ist dein Urteil?

Wirst du WPGraphQL bedingungslos für deine Headless-Anforderungen weiter nutzen?

Oder wirst du Gato GraphQL die Chance geben, die es beansprucht, das Plugin herunterladen und es ausprobieren?


Meine Damen und Herren. Das war alles für diese Nacht.

Wir hoffen aufrichtig, dass ihr den Kampf genossen habt.

Und hoffen wir, dass wir bald ein neues Treffen zwischen unseren beiden Champions haben werden.

Gute Nacht.

Update 01/05/2024: Erfahre mehr im Vergleich Gato GraphQL vs WPGraphQL.


Abonniere unseren Newsletter

Bleib über alle Updates zu Gato GraphQL auf dem Laufenden.