GraphQL-Grundlagen-Tutorial

08.07.2024 von Serdar Yegulalp
GraphQL ist für viele Devs die erste Wahl, um effiziente, zukunftsfähige APIs zu entwickeln. So gelingen die ersten Schritte mit dem Open-Source-Tool.
Dieser Artikel liefert Ihnen die Grundlagen, um mit GraphQL loszulegen.
Foto: Inspiration_GP | o_m | shutterstock.com

Die quelloffene REST-Alternative GraphQL ist ursprünglich den Entwicklungslaboren von Facebook entsprungen und seit 2018 als eigene Foundation unter dem Dach der Linux Foundation aktiv. Ähnlich wie REST ermöglicht auch GraphQL, webbasierte APIs zu erstellen und zu nutzen. Allerdings kommen dabei aus Konsistenzgründen formale Datenschemata und ein Type-System zum Einsatz.

Dieses Tutorial führt Sie durch die grundlegenden Schritte, die es braucht, um eine GraphQL-Schnittstelle zu designen und zu implementieren.

GraphQL-Sprachen und Frameworks

Falls Sie mit GraphQL als API für Ihre Webanwendungen planen, ist die Wahrscheinlichkeit hoch, dass Sie Ihre aktuelle Programmiersprache und Datenkomponenten beibehalten können. Schließlich sind GraphQL-Bibliotheken für so gut wie alle wichtigen Sprachen verfügbar, die in Produktionsumgebungen zum Einsatz kommen. Clients stehen zur Verfügung für:

Darüber hinaus decken die Serverbibliotheken weitere Bereiche ab.

Wenn Sie komplett "from scratch" beginnen, sind Sie gut damit beraten, die Programmiersprache, Laufzeitumgebung und Datenschicht zu wählen, mit der Sie am ehesten aus anderen Projekten vertraut sind. GraphQL zu nutzen, bringt hinsichtlich Server oder Client nicht viele Restriktionen mit sich - und es ist Datenbank-agnostisch. Mit Blick auf den Data Layer müssen Sie diesen allerdings eventuell manuell integrieren - je nachdem, um welche Art es sich dabei handelt (mehr dazu gleich).

Wir verwenden in diesem Artikel die Python-Implementierung von GraphQL als Referenz. Die Konzepte und Funktionen sind für andere Sprachen mehr oder weniger identisch.

Das GraphQL-Datenabfrageschema

GraphQL vearbeitet Queries, die aus stark typisierten Feldern in verschiedenen, hierarchischen Arrangements bestehen. Die wesentliche Frage, die Sie beantworten müssen, um eine GraphQL-API zu erstellen: Welches Schema soll für Datenabfragen bereitgestellt werden?

In vielen Fällen können die Abfragefelder eins zu eins auf eine zugrundeliegende Datenquelle abgebildet werden, um alle relevanten Felder in der Datenbank (oder einer anderen Datenquelle) für Ihre Queries offenzulegen. Weil GraphQL-Abfragen dabei im Vergleich zu ihren REST-Pendants wesentlich offener und variantenreicher sein können, sollten Sie von Beginn an planen,

Geht es zum Beispiel um eine Datenbanktabelle für Filme mit den Feldern title und year (als Ganzzahl), könnten wir eine GraphQL-Query wie die folgende verwenden:

type Character {

title: String!

year: Int

}

Das ! hinter String bedeutet, dass dieses Feld obligatorisch ist. In diesem Beispiel wäre als mindestens title nötig, um die Abfrage auszuführen.

Darüber hinaus sollten Sie sicherstellen, dass die Felder, die Sie über GraphQL exponieren, Typen nutzen, die mit den zugrundeligenden Daten übereinstimmen. GraphQL hat beispielsweise keinen nativen "date" oder "datetime" Datentypen - was im Wesentlichen an der schieren Menge verfügbarer Implementierungen liegt. Wenn Sie die Suche nach Datumsbereichen zulassen möchten, müssen Sie die Formatierung der Daten, die über die API einfließen, erzwingen und sicherstellen, dass diese bei der Abfrage in die entsprechenden Gegenstücke für die Backend-Datenbank übersetzt werden.

Die gute Nachricht: Es kann sein, dass diese Arbeit bereits für Sie erledigt wurde - je nachdem, welches Framework Sie verwenden. Graphene, eine populäre GraphQL-Bibliothek für Python, stellt ISO-8601-formatierte Datums- und Zeitwerte als nativen Typ zur Verfügung.

Falls Ihre Datensatz viele Felder aufweist, legen Sie zuerst die kleinste funktionale Teilmenge derjenigen offen, die keine komplexen Type Enforcements erfordern - etwa einfache String- oder Numerical Queries. Anschließend können Sie die verfügbaren Felder nach und nach erweitern, während Sie herausfinden, wie Sie Abfragen dafür über den von Ihnen verwendeten GraphQL-Connector implementieren.

GraphQL-Daten speichern und abrufen

Zum Speichern und Abrufen von Daten aus Ihrem Backend wird in der Regel die Middleware verwendet, die von der GraphQL-Bibliothek für Ihre Sprache unterstützt wird.

In vielen Fällen können Sie GraphQL diese Arbeit durch Datenschichten für gängige Anwendungsframeworks erledigen lassen. Die Python-Bibliothek Graphene für GraphQL unterstützt zum Beispiel das Web Framework Django und dessen integriertes ORM. Graphene unterstützt auch das ORM von SQLAlchemy, bietet darüber hinaus Support für Starlette sowie FastAPI und kann mit den Datenkonnektoren von Google App Engine sowie dem JavaScript-Framework Relay (wird von React genutzt) interagieren.

Falls Sie einen anderen Data Layer verwenden, können Sie die Middleware- und DataLoader-Objekte von Graphene nutzen, um die Lücke zu schließen. Diese bieten Ihnen die Möglichkeit, manuell zu integrieren. Mit DataLoader haben Sie auch die Möglichkeit, mehrere parallele Anfragen nach verwandten Daten zu bündeln und so die Anzahl der Roundtrips zu Ihrem Backend zu reduzieren.

Das schließt übrigens nicht aus, dass Sie selbst auf einem beliebigen Layer cachen. So könnten beispielsweise die von Ihnen zurückgegebenen Antworten über einen Proxy zwischengespeichert werden, während die Backend-Daten mit Memcached oder Redis zwischengespeichert werden könnten. Allerdings müssten Sie dann dafür sorgen, dass diese Zwischenspeicher bei jeder Datenänderung geleert werden.

Sie wollen weitere interessante Beiträge zu diversen Themen aus der IT-Welt lesen? Unsere kostenlosen Newsletter liefern Ihnen alles, was IT-Profis wissen sollten - direkt in Ihre Inbox!

Jetzt CW-Newsletter sichern

GraphQL-Mutation-Queries

Um Elemente in einem Datensatz zu erstellen, zu aktualisieren oder zu löschen, kommt bei GraphQL ein spezielles Abfrageformat zum Einsatz: die sogenannte "Mutation Query". Dabei gilt es nicht nur zu überdenken, welche Abfragen Sie zulassen und welche Felder Sie dafür benötigen, sondern auch, welche Daten nach der Mutation zurückgegeben werden.

Wenn Sie eine Mutationsabfrage entwerfen, können Sie die Rückgabe einer beliebigen Anzahl von Output-Feldern zulassen. Allerdings ist es wahrscheinlich keine gute Idee, Antwortobjekte über mehr als eine oder zwei Schichten zu verschachteln: Das erschwert es, die Ergebnisse zu analysieren - sowohl bei der Abfrage selbst als auch, wenn es darum geht, Code zu schreiben, der die Ergebnisse verarbeitet.

Ein Fallstrick, den Sie umgehen sollten: Lassen Sie sich nicht von alten REST-API-Designgewohnheiten leiten, wenn es darum geht, wie Sie Ihre Mutation Queries organisieren. Statt wie in REST beispielsweise mehrere Abfragen zu erstellen, um verschiedene Arten von Änderungen an ein und demselben Objekt zu behandeln, könnten Sie das in einer einzigen Mutation Query konsolidieren. Zum Beispiel, indem Sie unterschiedliche, nicht-optionale Felder verwenden, um jede mögliche Operation aufzuzeichnen - wie in diesem Beispiel.

Eine andere Möglichkeit wäre, eine Kombination aus einem Value-Feld und einem Enum Type zu verwenden, um das gewünschte Verhalten zu beschreiben. Ein wesentlicher Vorteil eines Enum ist, dass er eindeutig ist: Sie können ihn verwenden um den Intent präzise wiederzugeben - so dass er in hohem Maße selbstdokumentierend ist. Dabei stehen die Chancen gut, dass die GraphQL-Bibliothek für die Programmiersprache Ihrer Wahl eine Möglichkeit bietet, Enum Types im Einklang mit der sprachinternen Implementierung des Konzepts zu nutzen. Zum Beispiel können GraphQL-Enums in Graphene ganz ähnlich aussehen wie die Enum-Klasse der Python-Standardbibliothek.

GraphQL-Caching und -Performanceoptimierung

Eine GraphQL-Query fragt Daten im Grunde genommen wie jede andere Query ab. Deshalb lässt sie sich auch durch diesselben Methoden beschleunigen, die API-Abfragen mehr Speed verleihen:

GraphQL-Tools

Auch eine Reihe nativer Tools - und solche von Drittanbietern - stehen für GraphQL zur Verfügung, die es erleichtern, Clients, Server, Schemata und Query-Processing-Layer zu entwickeln:

(fm)

Dieser Beitrag basiert auf einem Artikel unserer US-Schwesterpublikation Infoworld.