Springe zu einem wichtigen Kapitel
Was ist GraphQL? Definition und Grundlagen
GraphQL ist eine spezifische Art der Datenabfrage und -manipulation für APIs. Damit sie effizient arbeitet, können Clients genau die Daten anfragen, die sie benötigen und erhalten diese genau so zurück, wie in der Anfrage festgelegt. Das resultiert in weniger Rundreisen zum Server und optimiert somit die Geschwindigkeit und Performance der Anwendung.
Die Kombination aus Anforderungen und zielgenauem Erhalt an Daten ermöglicht GraphQL, eine Alternative oder ein Ersatz für REST- und ad-hoc-Webservice-Architekturen zu sein. Da es API-übergreifend genutzt werden kann, ermöglicht es den Clienten, effizienter und präziser zu kommunizieren.
Die GraphQL Abfragesprache verstehen
Die GraphQL-Abfragesprache arbeitet mit drei grundlegenden Operationen: Abfragen (fragen die Daten ab), Mutationen (verändern die Daten) und Abonnements (melden sich zu Updates an). In einer Abfrage können verschiedene Felder ausgewählt und Daten von unterschiedlichen Ressourcen in einer einzigen Anfrage abgerufen werden. Dies differenziert GraphQL stark von REST-APIs, bei denen multiple Inhalte nur durch mehrere Anfragen erreichbar sind.
Ein Beispiel für eine GraphQL-Abfrage sieht so aus:
query { student (id: "1") { name age } }Hier fragen wir nach dem Namen und dem Alter eines Studenten mit der ID 1. Würden wir diese Informationen bei einer REST-API anfragen wollen, müssten wir unter Umständen mehrere Anfragen stellen.
Das GraphQL Datenmodellierungskonzept
Im Gegensatz zu relationalen Datenbanken, die Tabellen verwenden, arbeiten GraphQL-APIs mit einer Menge von Typen, der sogenannten "Schema Definition Language" (SDL). GraphQL bietet verschiedene Typen an, darunter Skalare, Enums, Interfaces und Unionstypen.
Die grundlegenden Typen (ObjectTypes) repräsentieren eine Art von Objekt, das du abrufen kannst. Jeder Typ hat eine Menge von Feldern, die eigene Typen haben können. Dies ermöglicht es Clients, genau die Daten abzurufen, die sie benötigen - nicht mehr und nicht weniger.
Volle Kontrolle mit GraphQL Mutation
Mutationen in GraphQL ermöglichen es Clients, Daten zu ändern. Sie sind vergleichbar mit den PUT, POST, PATCH und DELETE Methoden in REST-APIs. Mutationen folgen den gleichen strukturellen Regeln wie Abfragen, aber anstatt Daten abzurufen, werden sie geändert oder erstellt. Jede Mutation hat eine Reihe von Argumenten, die den wsie einer Funktion in anderen Programmiersprachen ähneln.
Mutationen in GraphQL sind serialisiert. Das bedeutet, sie werden nacheinander ausgeführt, statt alle auf einmal. Dies kann bedeutungsvoll sein, wenn mehrere Mutationen aufeinander aufbauen oder von den Ergebnissen anderer Mutationen abhängig sind.
GraphQL vs REST: Vorteile und Nachteile
Bei der Auswahl zwischen GraphQL und REST für die Anwendungsentwicklung gibt es eine Reihe von Faktoren zu berücksichtigen. Beide Technologien haben ihre eigenen Stärken und Schwächen und die Wahl hängt oft von den spezifischen Anforderungen eines Projekts ab.
Warum GraphQL eine Alternative zu REST ist
Die Abfrageflexibilität ist ein entscheidender Vorteil von GraphQL gegenüber REST. Da Clients nur die Daten anfordern können, die sie benötigen, wird Overfetching vermieden - ein häufiges Problem bei REST-APIs, wo die Antwort oft mehr Daten enthält, als benötigt.
Overfetching bedeutet, dass ein Client mehr Informationen anfordert, als er benötigt. Im Kontext von REST-APIs passiert das häufig, da die Datenstruktur fest vorgegeben ist. Mit GraphQL kann dieses Problem minimiert werden, da die Anfrage des Clients genau definiert, welche Daten benötigt werden, wodurch keine überschüssigen Informationen gesendet werden.
Zudem kann GraphQL dank der starken Typisierung dazu beitragen, dass die Datenqualität verbessert wird. Da der Typ jedes Felds im Schema definiert ist, kann GraphQL sicherstellen, dass die Clients immer die richtige Art von Daten erhalten und die Server immer korrekte Daten annehmen.
Ein Nachteil von GraphQL kann jedoch die erhöhte Komplexität sein. Während REST einfacher zu verstehen und zu nutzen ist, kann GraphQL aufgrund seiner Flexibilität und der Vielfalt an Optionen, die es bietet, komplizierter erscheinen.
Die Rolle von GraphQL Server und Client
Um GraphQL nutzen zu können, benötigst du sowohl einen GraphQL-Server als auch einen Client. Der Server ist dafür zuständig, Anfragen zu entgegen und Antworten zurückzusenden. Er prüft die Anfragen, validiert sie gegen das Schema und führt sie dann aus.
Um das besser zu verstehen, hier ein Beispielcode für einen einfachen GraphQL-Server in Node.js:
const express = require('express'); const graphqlHTTP = require('express-graphql'); const { buildSchema } = require('graphql'); const schema = buildSchema(` type Query { hello: String } `); const root = { hello: () => 'Hello world!' }; const app = express(); app.use('/graphql', graphqlHTTP({ schema: schema, rootValue: root, graphiql: true, })); app.listen(4000);In diesem Beispiel wird eine simple API erstellt, die bei der Anfrage \({ hello }\) die Antwort "Hello world!" ausgibt.
Der Client hingegen sendet Anfragen an den Server und verarbeitet die Antworten. Es gibt verschiedene GraphQL-Clients zur Auswahl, darunter Apollo Client, Relay und urql. Sie bieten Funktionen wie caching, pagination und Server state management.
Beispiele für den Einsatz von GraphQL und REST
Ein praktisches Beispiel, um den Unterschied zwischen GraphQL und REST zu illustrieren, ist die Datenabfrage in einer Blog-Anwendung. Angenommen, du möchtest die Kommentare zu einem bestimmten Blogbeitrag anzeigen.
In einer REST-Umgebung würdest du möglicherweise eine Anfrage an die /posts/{post_id}/comments Route senden, um eine Liste aller Kommentare zu diesem Beitrag zu erhalten. Je nachdem wie die REST-API aufgebaut ist, könnte die Antwort möglicherweise Informationen zu jedem Kommentar enthalten, die du nicht benötigst wie z.B. die IP-Adresse des Benutzers, der den Kommentar gepostet hat.
Bei Verwendung von GraphQL hingegen könntest du eine Anfrage wie diese senden:
query { post(id: "{post_id}") { comments { text author } } }Du erhältst dann genau die Daten, die du für deine Anwendung benötigst, ohne Overfetching, was zu einer effizienteren Netzwerkverwendung und häufig zu einer schnelleren Anwendung führt.
Hands-on mit GraphQL: Beispiele
Im Folgenden findest du praktische Beispiele, um ein besseres Verständnis für den Umgang mit GraphQL zu erhalten. Dabei lernst du, wie man eine einfache GraphQL-Abfrage erstellt, wie Apollo GraphQL genutzt wird und wie man GraphQL mit Datenbanken verknüpft.
Ein einfacher GraphQL Query erstellen
Um eine GraphQL-Anfrage zu erstellen, benötigst du nicht mehr als einen Endpunkt, der GraphQL unterstützt, und das Verständnis dafür, was du von diesem Endpunkt abrufen möchtest. Wenn du zum Beispiel die Daten eines Blogs abrufen möchtest, könntest du eine Abfrage erstellen, die den Titel und den Autor jedes Blogbeitrags abruft.
Die Syntax für solch eine Abfrage könnte folgendermaßen aussehen:
query { posts { title author } }Hiermit fragst du alle Blogbeiträge ab ('posts') und gibst an, dass du nur die Felder 'title' und 'author' erhalten möchtest.
Die Rückgabe deiner Anfrage wird genau der Struktur deiner Anfrage entsprechen. Für jedes Feld, das du in deiner Anfrage angegeben hast, wird der entsprechende Wert in der Rückgabedatenstruktur bereitgestellt. Dies ist einer der Hauptgründe, warum GraphQL Anklang findet - die Möglichkeit, genau zu spezifizieren, welche Daten der Client vom Server erhalten soll.
Arbeiten mit Apollo GraphQL: Ein Anleitungsbeispiel
Apollo ist eine weit verbreitete Implementierung von GraphQL, die sowohl auf dem Server als auch auf dem Client eingesetzt werden kann. In diesem Beispiel schauen wir uns an, wie du Apollo Client verwenden kannst, um eine GraphQL-Abfrage an einen Server zu senden.
Zunächst musst du Apollo Client in deinem Projekt installieren. Das kannst du tun, indem du folgenden Befehl in der Kommandozeile deines Projekts ausführst:
npm install @apollo/client graphql
Nach der Installation kannst du Apollo Client in deinem Code einrichten. Hierfür benötigst du die URL deines GraphQL-Servers. Mit dieser URL kann Apollo Client dann eine Verbindung zum Server herstellen und Anfragen senden.
Der entsprechende Code könnte so aussehen:
import { ApolloClient, InMemoryCache, gql } from "@apollo/client"; const client = new ApolloClient({ uri: 'https://api.example.com/graphql', cache: new InMemoryCache() }); client .query({ query: gql` { posts { title author } } ` }) .then(result => console.log(result));In diesem Code-Beispiel siehst du, wie du einen neuen Apollo Client erstellst und eine Anfrage an deinen GraphQL-Server sendest. Die Anfrage fragt alle Blogbeiträge ab und gibt den Titel und Autor jedes Beitrags zurück.
Es ist wichtig zu beachten, dass Apollo Client mehr bietet als nur die Möglichkeit, Abfragen zu senden. Mit Apollo Client kannst du auch Daten im Cache speichern, Pagination durchführen und sogar Client-seitigen Zustand verwalten. Apollo ist ein mächtiges Werkzeug in der GraphQL-Welt und wird in einer Vielzahl von Projekten eingesetzt.
Verknüpfen von GraphQL und Datenbanken
Eine der Schlüsselfunktionen von GraphQL ist die Fähigkeit, mit verschiedenen Datenquellen zu kommunizieren, einschließlich Datenbanken. Bei der Abfrage deines GraphQL-Servers gibt dieser die gewünschten Daten zurück. Aber woher kommen diese Daten? In den meisten Fällen kommen sie aus einer oder mehreren Datenbanken, die dein Server abfragt, wenn er eine Anfrage erhält.
GraphQL ist nicht an eine bestimmte Datenbank-Technologie gebunden. Du kannst eine SQL-Datenbank, eine NoSQL-Datenbank oder eine Kombination aus beiden verwenden. GraphQL agiert als effiziente, flexible Schicht zwischen dem Client und den Datenquellen, aber es liegt an dir, wie diese Datenquellen aussehen sollen. Das ist es, was GraphQL so mächtig und flexibel macht.
Für die Kommunikation mit den Datenbanken werden sogenannte "Resolver" genutzt. Ein Resolver ist eine Funktion, die die Daten für ein bestimmtes Feld in deinem Schema bereitstellt. In einem Resolver könntest du zum Beispiel eine Datenbank-Abfrage ausführen, um die Daten zu erhalten, die du zurückgeben möchtest.
Ein simples Beispiel könnte aussehen wie:
const resolvers = { Query: { posts: () => database.query('SELECT * FROM posts'), }, };In diesem Beispiel wird eine Datenbank-Abfrage ausgeführt, wenn die 'posts'-Anfrage aufgerufen wird. Der Resolver gibt dann die Antwort der Datenbank zurück.
Die Fähigkeit, Resolver zu definieren und so Daten auf Abruf aus einer Datenbank oder anderen Datenquellen abzurufen, ist einer der Hauptgründe, warum Entwickler GraphQL so schätzen. Es erlaubt die zielgenaue Abfrage von Daten und sorgt somit für optimale Performance und Effizienz.
Tiefer in GraphQL: Schema und Resolvers
Um die Vorteile von GraphQL voll ausschöpfen zu können, ist es wichtig, die Konzepte, die hinter der Technologie stehen, zu verstehen. Zwei zentrale Aspekte beim Arbeiten mit GraphQL sind das Schema und die Resolver. Das Schema legt fest, welche Operationen (Queries, Mutationen und Subscriptions) der Client ausführen kann und welche Daten er bei den entsprechenden Anfragen erhält. Die Resolver sind dafür zuständig, die tatsächlichen Daten für die Anfragen aus den Datenquellen zu holen.
Das Grundgerüst: GraphQL Schema
Das GraphQL Schema ist das Herzstück jeder GraphQL API und definieren die Struktur der Daten, die der Client erhält. Es besteht aus verschiedenen Typen, die die verschiedenen Datenstrukturen der API repräsentieren.
Es gibt drei spezielle Haupttypen im GraphQL Schema: Query, Mutation und Subscription.
- Query steht für alle Abfragen, die die Daten lesen, aber nicht verändern.
- Mutation steht für alle Abfragen, die Daten verändern, also Erstellen, Ändern und Löschen.
- Subscription ermöglicht das automatische Empfangen von Updates zu bestimmten Datenänderungen.
Die Definition eines Schemas mit der Schema Definition Language (SDL) könnte folgendermaßen aussehen:
type Query { posts: [Post] post(id: ID!): Post } type Mutation { createPost(title: String, author: String): Post } type Subscription { newPost: Post } type Post { id: ID title: String author: String }
Hier siehst du, wie die Abfragen, Mutationen und Entitäten definiert werden. Jeder Typ hat eine Reihe von Feldern, die ebenfalls Typen haben. Das erlaubt es GraphQL, die Struktur und die Typsicherheit der Daten zu garantieren. Für jedes Feld in einem Typ muss es einen Resolver geben, der im nächsten Abschnitt erklärt wird.
Die Praxis von GraphQL Resolvers
Resolver sind Funktionen, die für jeden Typ in einem Schema bestimmt sind. Jede Funktion liefert Daten für ein spezielles Feld. In gewisser Weise sind Resolver die Brücke zwischen den GraphQL-Typen im Schema und den Datenquellen, die die eigentlichen Daten liefern. Sie erweitern die Arbeit des Schemas, indem sie erklären, wie die Daten für die Felder geholt oder manipuliert werden.
Auf der grundlegendsten Ebene sieht ein Resolver folgendermaßen aus:
const resolvers = { Query: { posts: () => database.get('posts'), post: (_, { id }) => database.get('posts').find(post => post.id === id), }, Mutation: { createPost: (_, { title, author }) => { const post = { id: generateId(), title, author }; database.get('posts').push(post); return post; } } };Jeder Resolver entspricht einem Feld im Schema. Bei einer Anfrage oder Mutation führt GraphQL den entsprechenden Resolver aus und gibt das Ergebnis zurück.
In der Praxis können Resolvers auf die Datenbank, eine REST-API, einen In-Memory-Speicher oder jede andere Datenquelle zugreifen. Da GraphQL sich auf die Abfragestruktur und -Syntax konzentriert, nicht auf die Datenquellen selbst, bist du in der Wahl deiner Datenquellen extrem flexibel. Mit anderen Worten, du kannst die besten Ausführungsstrategien für deine spezifischen Anforderungen erschließen.
Praxisanweisungen für den Bau eines effizienten GraphQL API
Die Erstellung einer GraphQL API erfordert Sorgfalt und Planung, um Fehler und ineffiziente Datenabrufe zu vermeiden. Ein gut gestaltetes Schema und effiziente Resolvers können dazu beitragen, Over- und Underfetching zu vermeiden, Verzoegerungen zu reduzieren und eine schnelle API-Antwortzeit zu gewährleisten.
Zuallererst solltest du ein gut strukturiertes Schema erstellen. Es sollte alle wichtigen Daten und Beziehungen in deiner Applikation repräsentieren. Ein gutes Schema wird nicht nur die Entwicklung erleichtern, sondern auch zu einer besser strukturierten, einfacher zu wartenden Codebasis führen.
Hier sind ein paar Techniken, die dabei helfen, eine effiziente GraphQL API zu gestalten:
- Verwendung des DataLoader von Facebook, um das N+1-Problem zu vermeiden und Datenlade-Operationen zu batchen und zu cachen.
- Bereitstellen detaillierter Fehlermeldungen, damit der Client genau weiß, was schief gelaufen ist. GraphQL hat integrierte Fehlerbehandlungsfunktionen, die genutzt werden sollten.
- Vermeidung übermäßiger Verschachtelung. Obwohl GraphQL Verschachtelung zulässt, kann zu viel davon die Abfragen verlangsamen und den Overhead erhöhen.
- Profiling deiner Resolvers, um zu erkennen, welche am meisten Zeit benötigen und möglicherweise optimiert werden sollten.
Das N+1-Problem entsteht, wenn der Server ein Element und dann eine Liste aller zugehörigen Elemente laden muss, was zu einer großen Anzahl von Anfragen führen kann. DataLoader ist eine Bibliothek, die dieses Problem löst, indem sie Anfragen zu Batches zusammenfasst und redundanten Zugriff auf die Datenquelle reduziert.
Zusammenfassend lässt sich sagen, dass das Erstellen einer effizienten GraphQL API eine Herausforderung sein kann, aber die Flexibilität und Kontrolle, die sie bieten, machen sie zu einer attraktiven Wahl für viele Entwickler.
Weiterführende Themen in GraphQL
Die mächtigen Konzepte von GraphQL enden nicht bei Queries, Mutationen und Subscriptions. Es gibt viele weiterführende Aspekte, mit denen du dein Wissen vertiefen und gleichzeitig deine Fähigkeiten als Entwickler erweitern kannst. Dazu gehören Themen wie die Erstellung von benutzerdefinierten Direktiven, Fehlerbehandlung, das Arbeiten mit Interfaces und Union Types sowie das Anwenden fortgeschrittener Konzepte der Webentwicklung mit GraphQL.
Möglichkeiten und Grenzen der Datenabfrage mit GraphQL
Während GraphQL viele mächtige Abfragefunktionen bietet, gibt es auch Grenzen, die du kennen solltest. Doese Grenzen sind notwendig, um die Serverperformance zu schützen und Missbrauch vorzubeugen.
Eine weit verbreitete Form der Restriktion ist die sogenannte "Depth Limiting". Sie beschränkt die maximal zulässige Tiefe einer Abfrage hierarchie. Dies ist besonders wichtig, um rekursive Abfragen zu verwalten, die das Potenzial haben, deinen Server stark zu belasten.
Ein Beispiel für Depth Limiting wäre, wenn du eine Abfrage hättest, die den Autor eines Beitrags, die Beiträge dieses Autors, die Autoren dieser Beiträge und so weiter anfordert. Ohne Depth Limiting könnte diese Abfrage sehr groß werden und eine erhebliche Last auf den Server legen.
Solche Beschränkungen können mithilfe von Tools zur Validierung und Analyse von GraphQL-Queries umgesetzt werden. Mithilfe dieser Tools kann der Server prüfen, ob eine Abfrage gültig ist und nicht die festgelegten Beschränkungen übersteigt, bevor sie ausgeführt wird.
Darüber hinaus gibt es noch weitere fortgeschrittene Techniken zum Umgang mit großen Datenmengen in GraphQL wie Pagination, Caching und Batch-Loading. Diese Techniken sind Teil der "Best Practices" bei der Arbeit mit GraphQL und können dazu beitragen, dass dein Server effizient bleibt, selbst wenn das Datenaufkommen steigt.
Von der Theorie zur Praxis: Real Life Anwendung von GraphQL
Die wahre Kraft von GraphQL wird deutlich, wenn wir konkrete Anwendungsfälle betrachten. Große Unternehmen wie Facebook, GitHub und Airbnb nutzen GraphQL, um flexible und effiziente APIs für ihre Produkte zu schaffen.
GitHub zum Beispiel hat GraphQL genutzt, um seine öffentliche API zu überarbeiten. Mit GraphQL konnte GitHub viele verschiedenen API-Endpunkte in einer einzigen, einheitlichen Schnittstelle zusammenfassen. Das ermöglicht Entwicklern eine größere Flexibilität und Effizienz bei der Nutzung der GitHub-API.
Ein Entwickler, der die GitHub-API nutzt, könnte beispielsweise eine einzelne Anfrage stellen, um alle öffentlichen Repositories eines Benutzers, zusammen mit den neuesten Commits für jedes Repository, abzurufen, anstatt mehrere einzelne Anfragen stellen zu müssen. Das sieht dann in etwa so aus:
query { user(login: "username") { repositories(first: 10) { edges { node { name ref(qualifiedName: "master") { target { ... on Commit { history(first: 10) { edges { node { message author { name } } } } } } } } } } } }
Mit GraphQL kann der Entwickler eine einzige, personalisierte Anfrage stellen und erhält genau die Daten, die er braucht, wodurch Over- und Underfetching vermieden werden.
GraphQL für fortgeschrittene Webentwicklung
GraphQL bringt viele Konzepte mit, die für fortgeschrittene Webentwicklung sehr nützlich sein können. Eines davon ist das Konzept der "direktiven". Mit Direktiven kannst du die Ausführung von Queries und Mutationen auf vielfältige Weise beeinflussen.
Direktiven sind Markierungen, die in der Abfragesprache von GraphQL vorkommen und die Ausführung von Teilen einer Abfrage modifizieren können. Du kannst zum Beispiel mit ihnen bestimmte Felder in deinen Responses deaktivieren oder rekursive Abfragen begrenzen.
Ein einfaches Beispiel für die Verwendung einer Direktive ist die @include-Direktive, die in der GraphQL-Spezifikation definiert ist. Mit dieser Direktive kannst du dynamisch entscheiden, ob ein Feld in der Antwort enthalten sein soll oder nicht, basierend auf einer variablen Bedingung:
query($includeAuthor: Boolean!) { posts { title author @include(if: $includeAuthor) } }In diesem Beispiel wird das Feld 'author' nur dann in der Antwort enthalten sein, wenn die Variable $includeAuthor den Wert 'true' hat.
In der fortgeschrittenen Webentwicklung sind Direktiven ein mächtiges Werkzeug zur Modifizierung der Anfragen. Mit ihnen kannst du die Anfragen an deine speziellen Anforderungen anpassen.
GraphQL - Das Wichtigste
- GraphQL verbessert die Datenqualität durch strikte Typisierung und Datenvalidierung basierend auf dem Schema
- Eine Herausforderung bei der Verwendung von GraphQL kann die erhöhte Komplexität im Vergleich zu REST sein
- GraphQL-Server nimmt Anfragen an und sendet Antworten, während Client Anfragen sendet und Antworten verarbeitet
- GraphQL ermöglicht präzises Abfragen von Daten, was Overfetching verhindert und zu besserer Performance führt
- Resolver in GraphQL sind Funktionen, die Daten für bestimmte Felder in einem Schema bereitstellen, oft durch Abfragen von Datenbanken
- GraphQL-Schema definiert die Datenstruktur der API und besteht aus Typen, die verschiedene Datenstrukturen repräsentieren
Lerne mit 10 GraphQL Karteikarten in der kostenlosen StudySmarter App
Du hast bereits ein Konto? Anmelden
Häufig gestellte Fragen zum Thema GraphQL
Über StudySmarter
StudySmarter ist ein weltweit anerkanntes Bildungstechnologie-Unternehmen, das eine ganzheitliche Lernplattform für Schüler und Studenten aller Altersstufen und Bildungsniveaus bietet. Unsere Plattform unterstützt das Lernen in einer breiten Palette von Fächern, einschließlich MINT, Sozialwissenschaften und Sprachen, und hilft den Schülern auch, weltweit verschiedene Tests und Prüfungen wie GCSE, A Level, SAT, ACT, Abitur und mehr erfolgreich zu meistern. Wir bieten eine umfangreiche Bibliothek von Lernmaterialien, einschließlich interaktiver Karteikarten, umfassender Lehrbuchlösungen und detaillierter Erklärungen. Die fortschrittliche Technologie und Werkzeuge, die wir zur Verfügung stellen, helfen Schülern, ihre eigenen Lernmaterialien zu erstellen. Die Inhalte von StudySmarter sind nicht nur von Experten geprüft, sondern werden auch regelmäßig aktualisiert, um Genauigkeit und Relevanz zu gewährleisten.
Erfahre mehr