In der sich ständig weiterentwickelnden Landschaft der Webentwicklung hat sich GraphQL als leistungsstarke Alternative zu traditionellen REST-APIs etabliert und bietet Clients die Möglichkeit, genau die Daten anzufordern, die sie benötigen. Diese Flexibilität kann jedoch eine Reihe neuer Herausforderungen mit sich bringen, insbesondere wenn es darum geht, die Typsicherheit zwischen Frontend und Backend aufrechtzuerhalten. Hier kommt graphql-codegen
ins Spiel, ein revolutionäres Tool, das die Generierung von typisiertem Code aus Ihrem GraphQL-Schema automatisiert, Ihren Entwicklungs-Workflow beschleunigt und eine ganze Klasse von Laufzeitfehlern eliminiert.
Dieser Artikel dient als Ihr Leitfaden zum Verständnis und zur Beherrschung von graphql-codegen
. Wir beginnen mit den grundlegenden Konzepten, gehen ein praktisches Schritt-für-Schritt-Beispiel für die Einrichtung und Konfiguration des Tools durch und erkunden Best Practices für die Integration in Ihre Projekte. Am Ende dieses Leitfadens sind Sie in der Lage, graphql-codegen
zu nutzen, um robustere, wartungsfreundlichere und typsichere Anwendungen zu erstellen.
Möchten Sie eine integrierte All-in-One-Plattform für Ihr Entwicklerteam, um mit maximaler Produktivität zusammenzuarbeiten?
Apidog erfüllt all Ihre Anforderungen und ersetzt Postman zu einem viel günstigeren Preis!
Was ist graphql-codegen
und warum brauchen Sie es?
Im Kern ist graphql-codegen
ein Befehlszeilen-Tool, das Ihr GraphQL-Schema und Ihre GraphQL-Operationen (Queries, Mutations und Subscriptions) introspektiert und Code in einer Vielzahl von Sprachen generiert. Für die Zwecke dieses Anfängerleitfadens konzentrieren wir uns auf den populärsten Anwendungsfall: die Generierung von TypeScript-Typen und Hooks für Frontend-Anwendungen.
Das Hauptproblem, das graphql-codegen
löst, ist der mühsame und fehleranfällige Prozess des manuellen Schreibens von TypeScript-Interfaces für die Datenstrukturen Ihrer GraphQL-API und die Ergebnisse Ihrer Queries. Ohne dieses Tool müssten Entwickler entweder mit untypisierten Daten arbeiten (und die Vorteile von TypeScript verlieren) oder erhebliche Zeit damit verbringen, Typen zu erstellen und zu pflegen, die mit der Weiterentwicklung der API leicht veralten können.
Die Vorteile der Einführung von graphql-codegen
sind vielfältig:
- End-to-End-Typsicherheit: Durch die Generierung von Typen direkt aus Ihrem Schema stellt
graphql-codegen
sicher, dass Ihr Frontend-Code immer mit dem Datenmodell Ihres Backends synchron ist. Das bedeutet, dass Sie typbezogene Fehler zur Kompilierungszeit abfangen, lange bevor sie Ihre Benutzer erreichen. - Verbesserte Entwicklererfahrung: Mit generierten Typen erhalten Sie Funktionen wie Autovervollständigung und intelligente Vorschläge in Ihrem Code-Editor, was die Entwicklung schneller und effizienter macht. Kein Rätselraten mehr über die Form Ihrer API-Antworten!
- Reduzierter Boilerplate-Code:
graphql-codegen
kann nicht nur Typen generieren, sondern auch gebrauchsfertige Hooks für beliebte GraphQL-Clients wie Apollo Client und React Query. Dies eliminiert die Notwendigkeit, sich wiederholende Datenabruflogik zu schreiben. - Verbesserte Wartbarkeit: Wenn sich Ihr API-Schema ändert, genügt ein einfacher Befehl, um Ihre Typen neu zu generieren. Dies macht Ihre Codebasis im Laufe der Zeit viel einfacher zu warten und zu refaktorieren.
Dieser Ansatz passt perfekt zur "Schema-First"-Entwicklungsphilosophie, bei der das GraphQL-Schema als einzige Quelle der Wahrheit für Ihre API dient.
Erste Schritte: Ihr erstes graphql-codegen
Setup
Tauchen wir ein in die praktischen Aspekte der Verwendung von graphql-codegen
. Für dieses Tutorial gehen wir davon aus, dass Sie ein grundlegendes Verständnis von GraphQL und TypeScript haben und Node.js sowie einen Paketmanager (wie npm oder yarn) installiert haben.
Unser Ziel ist es, graphql-codegen
für eine einfache React-Anwendung einzurichten, die eine Liste von Blogbeiträgen anzeigt.
Schritt 1: Projektinitialisierung und Abhängigkeiten
Erstellen wir zunächst ein neues React-Projekt mit TypeScript und installieren die notwendigen Abhängigkeiten.Bash
npx create-react-app my-blog --template typescript
cd my-blog
npm install @apollo/client graphql
npm install -D @graphql-codegen/cli @graphql-codegen/client-preset typescript
Hier ist eine Aufschlüsselung der installierten Abhängigkeiten:
@apollo/client
: Ein beliebter GraphQL-Client für React.graphql
: Eine Peer-Abhängigkeit, die sowohl von Apollo Client als auch vongraphql-codegen
benötigt wird.@graphql-codegen/cli
: Die Befehlszeilenschnittstelle fürgraphql-codegen
.@graphql-codegen/client-preset
: Ein modernes und optimiertes Preset, das die Konfiguration für clientseitige Anwendungen vereinfacht.typescript
: Der TypeScript-Compiler.
Schritt 2: Der graphql-codegen
Initialisierungs-Wizard
Der einfachste Weg, mit graphql-codegen
zu beginnen, ist die Verwendung des Initialisierungs-Wizards. Führen Sie den folgenden Befehl im Stammverzeichnis Ihres Projekts aus:Bash
npx graphql-codegen init
Der Wizard stellt Ihnen eine Reihe von Fragen, um die Konfiguration Ihres Projekts zu erleichtern. Hier ist eine typische Reihe von Antworten für unser Bloganwendungsszenario:
- Welchen Anwendungstyp erstellen Sie?
Application built with React
- Wo befindet sich Ihr Schema? Geben Sie die URL zu Ihrem GraphQL API-Endpunkt an. Für dieses Tutorial können wir eine öffentlich verfügbare Beispiel-API verwenden:
https://swapi-graphql.netlify.app/.netlify/functions/index
- Wo befinden sich Ihre Operationen und Fragmente?
src/**/*.tsx
(Dies weistgraphql-codegen
an, in allen.tsx
-Dateien innerhalb dessrc
-Verzeichnisses nach GraphQL-Queries zu suchen). - Plugins auswählen: Der Wizard schlägt eine Reihe von Plugins vor. Die Standardeinstellungen, einschließlich
typescript
,typescript-operations
undtypescript-react-apollo
, sind ein großartiger Ausgangspunkt. - Wo soll die Ausgabe geschrieben werden?
src/gql/
(Dadurch wird ein neues Verzeichnissrc/gql
erstellt, um die generierten Dateien zu speichern). - Möchten Sie eine Introspektionsdatei generieren?
Yes
(Dies kann für die lokale Entwicklung und IDE-Erweiterungen nützlich sein). - Wie soll die Konfigurationsdatei benannt werden?
codegen.ts
- Welches Skript in package.json soll den Codegen ausführen?
codegen
Nachdem Sie diese Fragen beantwortet haben, erstellt der Wizard eine Datei codegen.ts
im Stammverzeichnis Ihres Projekts und fügt ein codegen
-Skript zu Ihrer package.json
hinzu.
Schritt 3: Verständnis der Konfigurationsdatei (codegen.ts
)
Die Datei codegen.ts
ist das Herzstück Ihres graphql-codegen
Setups. Werfen wir einen Blick auf eine vereinfachte Version dessen, was der Wizard generiert:TypeScript
import type { CodegenConfig } from '@graphql-codegen/cli';
const config: CodegenConfig = {
overwrite: true,
schema: "https://swapi-graphql.netlify.app/.netlify/functions/index",
documents: "src/**/*.tsx",
generates: {
"src/gql/": {
preset: "client",
plugins: []
}
}
};
export default config;
Schlüsseln wir die wichtigsten Konfigurationsoptionen auf:
overwrite: true
: Dies stellt sicher, dass vorhandene generierte Dateien bei jedem Ausführen des Befehls überschrieben werden.schema
: Dies verweist auf die Quelle Ihres GraphQL-Schemas. Es kann eine URL zu einem Live-Endpunkt, eine lokale.graphql
- oder.json
-Datei sein.documents
: Dies ist ein Glob-Muster, dasgraphql-codegen
mitteilt, wo Ihre GraphQL-Operationen (Queries, Mutations und Fragmente) zu finden sind.generates
: Dies ist der wichtigste Teil der Konfiguration. Es ist ein Objekt, bei dem jeder Schlüssel eine Ausgabedatei oder ein Verzeichnis darstellt und der Wert definiert, was generiert werden soll.preset: "client"
: Dasclient-preset
ist eine leistungsstarke und empfohlene Methode zur Konfiguration vongraphql-codegen
für Frontend-Anwendungen. Es bündelt mehrere Plugins und bietet eine optimierte Erfahrung. Es generiert einegraphql
-Funktion, die Sie zum Schreiben Ihrer Queries verwenden werden.
Schritt 4: Schreiben Ihrer ersten GraphQL-Query
Nachdem graphql-codegen
konfiguriert ist, schreiben wir eine GraphQL-Query, um unsere Blogbeiträge abzurufen. Erstellen Sie eine neue Datei src/components/Posts.tsx
:TypeScript
import { gql } from '../gql/gql';
import { useQuery } from '@apollo/client';
const GET_POSTS = gql(`
query GetPosts {
allFilms {
films {
id
title
director
releaseDate
}
}
}
`);
const Posts = () => {
const { loading, error, data } = useQuery(GET_POSTS);
if (loading) return <p>Loading...</p>;
if (error) return <p>Error :(</p>;
return (
<div>
{data?.allFilms?.films?.map((film) => (
<div key={film?.id}>
<h2>{film?.title}</h2>
<p>Director: {film?.director}</p>
<p>Release Date: {film?.releaseDate}</p>
</div>
))}
</div>
);
};
export default Posts;
Beachten Sie, dass wir eine gql
-Funktion aus der generierten Datei src/gql/gql.ts
importieren. Dies ist die vom client-preset
bereitgestellte gql
-Funktion und ermöglicht die Magie der Typinferenz.
Schritt 5: Ausführen von graphql-codegen
und die Magie sehen
Führen Sie nun das codegen
-Skript aus Ihrer package.json
aus:Bash
npm run codegen
Dieser Befehl introspektiert das Schema, findet Ihre GET_POSTS
-Query und generiert die entsprechenden TypeScript-Typen im Verzeichnis src/gql
.
Wenn Sie nun das data
-Objekt inspizieren, das vom useQuery
-Hook in Posts.tsx
zurückgegeben wird, werden Sie sehen, dass es vollständig typisiert ist! Ihre IDE bietet Autovervollständigung für data.allFilms.films
, und TypeScript warnt Sie, wenn Sie versuchen, auf ein Feld zuzugreifen, das in der Query nicht existiert.
Ein tieferer Einblick: Ein praktisches Blog-Frontend-Beispiel
Erweitern wir unser Beispiel, um Ihr Verständnis zu festigen. Stellen Sie sich vor, unser Blog hat ein traditionelleres Schema:GraphQL
type Author {
id: ID!
name: String!
}
type Post {
id: ID!
title: String!
content: String!
author: Author!
}
type Query {
posts: [Post!]!
post(id: ID!): Post
}
type Mutation {
createPost(title: String!, content: String!, authorId: ID!): Post!
}
Nehmen wir an, dieses Schema läuft unter http://localhost:4000/graphql
. Wir würden unsere codegen.ts
entsprechend aktualisieren:TypeScript
// codegen.ts
// ...
schema: "http://localhost:4000/graphql",
// ...
Nun erstellen wir eine Komponente zur Anzeige eines einzelnen Beitrags und eine weitere zur Erstellung eines neuen Beitrags.
Abrufen eines einzelnen BeitragsTypeScript
// src/components/Post.tsx
import { gql } from '../gql/gql';
import { useQuery } from '@apollo/client';
import { useParams } from 'react-router-dom';
const GET_POST = gql(`
query GetPost($id: ID!) {
post(id: $id) {
id
title
content
author {
id
name
}
}
}
`);
const Post = () => {
const { id } = useParams<{ id: string }>();
const { loading, error, data } = useQuery(GET_POST, {
variables: { id },
});
if (loading) return <p>Loading...</p>;
if (error) return <p>Error :(</p>;
return (
<div>
<h2>{data?.post?.title}</h2>
<p>By {data?.post?.author?.name}</p>
<p>{data?.post?.content}</p>
</div>
);
};
export default Post;
Nachdem Sie npm run codegen
ausgeführt haben, werden die Typen für die GetPostQuery
und ihre Variablen generiert, was Typsicherheit für den useQuery
-Hook und sein Ergebnis bietet.
Erstellen eines neuen BeitragsTypeScript
// src/components/CreatePost.tsx
import { gql } from '../gql/gql';
import { useMutation } from '@apollo/client';
import { useState } from 'react';
const CREATE_POST = gql(`
mutation CreatePost($title: String!, $content: String!, $authorId: ID!) {
createPost(title: $title, content: $content, authorId: $authorId) {
id
}
}
`);
const CreatePost = () => {
const [title, setTitle] = useState('');
const [content, setContent] = useState('');
const [createPost, { data, loading, error }] = useMutation(CREATE_POST);
const handleSubmit = (e: React.FormEvent) => {
e.preventDefault();
createPost({ variables: { title, content, authorId: '1' } }); // Assuming authorId '1' for simplicity
};
return (
<form onSubmit={handleSubmit}>
<input
type="text"
placeholder="Title"
value={title}
onChange={(e) => setTitle(e.target.value)}
/>
<textarea
placeholder="Content"
value={content}
onChange={(e) => setContent(e.target.value)}
/>
<button type="submit" disabled={loading}>
{loading ? 'Creating...' : 'Create Post'}
</button>
{error && <p>Error creating post: {error.message}</p>}
{data && <p>Post created with ID: {data.createPost.id}</p>}
</form>
);
};
export default CreatePost;
Hier generiert graphql-codegen
die Typen für die CreatePostMutation
und ihre Variablen. Dies stellt sicher, dass Sie beim Aufruf der createPost
-Funktion die korrekten Typen für title
, content
und authorId
übergeben.
Fortgeschrittene Konzepte und Best Practices
Wenn Sie sich mit graphql-codegen
vertraut gemacht haben, werden Sie auf fortgeschrittenere Funktionen und Best Practices stoßen:
Fragmente: graphql-codegen
unterstützt GraphQL-Fragmente hervorragend. Sie können Fragmente in Ihren .tsx
-Dateien definieren, und graphql-codegen
behandelt die Typen korrekt, was wiederverwendbare und co-lokalisierte Datenabhängigkeiten für Ihre Komponenten fördert.
Verwenden von .graphql
-Dateien: Für eine bessere Trennung der Belange können Sie Ihre GraphQL-Queries, Mutations und Fragmente in dedizierten .graphql
-Dateien schreiben. Aktualisieren Sie einfach das documents
-Array in Ihrer codegen.ts
, um diese Dateierweiterung einzuschließen: documents: ["src/**/*.tsx", "src/**/*.graphql"]
.
Benutzerdefinierte Skalare: Wenn Ihr GraphQL-Schema benutzerdefinierte Skalare (z. B. Date
, JSON
) verwendet, können Sie diese in Ihrer codegen.ts
-Datei entsprechenden TypeScript-Typen zuordnen, um die Typsicherheit aufrechtzuerhalten.
Watch Mode: Für eine nahtlose Entwicklungserfahrung können Sie graphql-codegen
im Watch Mode ausführen. Dadurch werden Ihre Typen automatisch neu generiert, wenn Sie eine Datei speichern, die eine GraphQL-Operation enthält. Fügen Sie einfach ein --watch
-Flag zu Ihrem codegen
-Skript in package.json
hinzu: "codegen": "graphql-codegen --watch"
.
Fehlerbehebung bei häufigen Problemen
Obwohl graphql-codegen
ein leistungsstarkes Tool ist, können Sie als Anfänger auf einige häufige Probleme stoßen:
- "Unable to find schema": Dieser Fehler bedeutet normalerweise, dass der
schema
-Pfad in Ihrercodegen.ts
falsch ist oder der GraphQL-Server nicht unter der angegebenen Adresse läuft. - Plugin-Konfigurationsfehler: Stellen Sie sicher, dass Sie alle notwendigen Plugins installiert haben und dass ihre Konfigurationen in
codegen.ts
korrekt sind. graphql
Peer-Abhängigkeitsprobleme: Stellen Sie sicher, dass Siegraphql
als direkte Abhängigkeit in Ihrem Projekt installiert haben.
Fazit: Umarmen Sie die typsichere Zukunft
graphql-codegen
ist mehr als nur ein Code-Generierungstool; es ist ein Paradigmenwechsel in der Art und Weise, wie wir Anwendungen mit GraphQL erstellen. Durch die Nutzung von Automatisierung und die Stärke Ihres Schemas können Sie robustere, wartungsfreundlichere und angenehmer zu bearbeitende Codebasen erstellen.
Dieses Tutorial hat Ihnen eine solide Grundlage für den Einstieg in graphql-codegen
gegeben. Wir haben die Kernkonzepte behandelt, ein praktisches Beispiel durchgearbeitet und Best Practices angesprochen. Die Reise endet hier nicht. Das graphql-codegen
-Ökosystem ist riesig, mit einer reichen Sammlung von Plugins, die verschiedene Frameworks und Anwendungsfälle abdecken. Ich ermutige Sie, die offizielle Dokumentation zu erkunden, mit verschiedenen Plugins zu experimentieren und zu entdecken, wie graphql-codegen
Ihren GraphQL-Entwicklungs-Workflow revolutionieren kann. Viel Spaß beim Codieren!
Möchten Sie eine integrierte All-in-One-Plattform für Ihr Entwicklerteam, um mit maximaler Produktivität zusammenzuarbeiten?
Apidog erfüllt all Ihre Anforderungen und ersetzt Postman zu einem viel günstigeren Preis!