Dans le paysage en constante évolution du développement web, GraphQL est apparu comme une alternative puissante aux API REST traditionnelles, offrant aux clients la possibilité de demander précisément les données dont ils ont besoin. Cependant, cette flexibilité peut introduire un nouvel ensemble de défis, en particulier lorsqu'il s'agit de maintenir la sécurité des types entre le frontend et le backend. C'est là qu'intervient graphql-codegen
, un outil révolutionnaire qui automatise la génération de code typé à partir de votre schéma GraphQL, dynamisant votre flux de travail de développement et éliminant toute une classe d'erreurs d'exécution.
Cet article vous servira de guide pour comprendre et maîtriser graphql-codegen
. Nous commencerons par les concepts fondamentaux, passerons par un exemple pratique étape par étape de configuration de l'outil, et explorerons les meilleures pratiques pour l'intégrer dans vos projets. À la fin de ce guide, vous serez équipé pour tirer parti de graphql-codegen
afin de construire des applications plus robustes, maintenables et sûres en termes de types.
Vous voulez une plateforme intégrée, tout-en-un, pour que votre équipe de développeurs travaille ensemble avec une productivité maximale ?
Apidog répond à toutes vos demandes et remplace Postman à un prix beaucoup plus abordable !
Qu'est-ce que graphql-codegen
et pourquoi en avez-vous besoin ?
À la base, graphql-codegen
est un outil en ligne de commande qui introspecte votre schéma GraphQL et vos opérations GraphQL (requêtes, mutations et abonnements) et génère du code dans une variété de langages. Dans le cadre de ce guide pour débutants, nous nous concentrerons sur son cas d'utilisation le plus populaire : la génération de types TypeScript et de hooks pour les applications frontend.
Le principal problème que graphql-codegen
résout est le processus fastidieux et sujet aux erreurs de l'écriture manuelle d'interfaces TypeScript pour les structures de données de votre API GraphQL et les résultats de vos requêtes. Sans cela, les développeurs sont soit obligés de travailler avec des données non typées (perdant les avantages de TypeScript), soit de passer un temps considérable à créer et maintenir des types qui peuvent facilement devenir obsolètes à mesure que l'API évolue.
Les avantages de l'adoption de graphql-codegen
sont multiples :
- Sécurité des types de bout en bout : En générant des types directement à partir de votre schéma,
graphql-codegen
garantit que votre code frontend est toujours synchronisé avec le modèle de données de votre backend. Cela signifie que vous détectez les erreurs liées aux types au moment de la compilation, bien avant qu'elles n'atteignent vos utilisateurs. - Amélioration de l'expérience développeur : Avec les types générés, vous bénéficiez de fonctionnalités telles que l'autocomplétion et les suggestions intelligentes dans votre éditeur de code, ce qui rend le développement plus rapide et plus efficace. Fini les devinettes sur la forme des réponses de votre API !
- Réduction du code répétitif (Boilerplate) :
graphql-codegen
peut générer non seulement des types, mais aussi des hooks prêts à l'emploi pour les clients GraphQL populaires comme Apollo Client et React Query. Cela élimine le besoin d'écrire une logique de récupération de données répétitive. - Maintenance améliorée : Lorsque le schéma de votre API change, une simple commande suffit pour régénérer vos types. Cela rend votre base de code beaucoup plus facile à maintenir et à refactoriser au fil du temps.
Cette approche s'aligne parfaitement avec la philosophie de développement "schema-first", où le schéma GraphQL sert de source unique de vérité pour votre API.
Premiers pas : Votre première configuration graphql-codegen
Plongeons dans les aspects pratiques de l'utilisation de graphql-codegen
. Pour ce tutoriel, nous supposerons que vous avez une compréhension de base de GraphQL, TypeScript, et que vous avez Node.js et un gestionnaire de paquets (comme npm ou yarn) installés.
Notre objectif est de configurer graphql-codegen
pour une simple application React qui affiche une liste d'articles de blog.
Étape 1 : Initialisation du projet et dépendances
Tout d'abord, créons un nouveau projet React avec TypeScript et installons les dépendances nécessaires.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
Voici une description des dépendances que nous avons installées :
@apollo/client
: Un client GraphQL populaire pour React.graphql
: Une dépendance pair requise par Apollo Client etgraphql-codegen
.@graphql-codegen/cli
: L'interface en ligne de commande pourgraphql-codegen
.@graphql-codegen/client-preset
: Un preset moderne et simplifié qui facilite la configuration pour les applications côté client.typescript
: Le compilateur TypeScript.
Étape 2 : L'assistant d'initialisation graphql-codegen
La manière la plus simple de commencer avec graphql-codegen
est d'utiliser son assistant d'initialisation. Exécutez la commande suivante à la racine de votre projet :Bash
npx graphql-codegen init
L'assistant vous posera une série de questions pour vous aider à configurer votre projet. Voici un ensemble de réponses typiques pour notre scénario d'application de blog :
- Quel type d'application construisez-vous ?
Application construite avec React
- Où se trouve votre schéma ? Fournissez l'URL de votre point de terminaison API GraphQL. Pour ce tutoriel, nous pouvons utiliser une API d'exemple publiquement disponible :
https://swapi-graphql.netlify.app/.netlify/functions/index
- Où sont vos opérations et fragments ?
src/**/*.tsx
(Cela indique àgraphql-codegen
de rechercher les requêtes GraphQL dans tous les fichiers.tsx
du répertoiresrc
). - Choisissez les plugins : L'assistant suggérera un ensemble de plugins. Les valeurs par défaut, y compris
typescript
,typescript-operations
ettypescript-react-apollo
, sont un excellent point de départ. - Où écrire la sortie ?
src/gql/
(Cela créera un nouveau répertoiresrc/gql
pour stocker les fichiers générés). - Voulez-vous générer un fichier d'introspection ?
Oui
(Cela peut être utile pour le développement local et les extensions d'IDE). - Comment nommer le fichier de configuration ?
codegen.ts
- Quel script dans package.json doit exécuter codegen ?
codegen
Après avoir répondu à ces questions, l'assistant créera un fichier codegen.ts
à la racine de votre projet et ajoutera un script codegen
à votre package.json
.
Étape 3 : Comprendre le fichier de configuration (codegen.ts
)
Le fichier codegen.ts
est le cœur de votre configuration graphql-codegen
. Jetons un coup d'œil à une version simplifiée de ce que l'assistant génère :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;
Décortiquons les principales options de configuration :
overwrite: true
: Cela garantit que les fichiers générés existants sont écrasés à chaque exécution de la commande.schema
: Ceci pointe vers la source de votre schéma GraphQL. Il peut s'agir d'une URL vers un point de terminaison en direct, d'un fichier local.graphql
ou.json
.documents
: Il s'agit d'un modèle glob qui indique àgraphql-codegen
où trouver vos opérations GraphQL (requêtes, mutations et fragments).generates
: C'est la partie la plus importante de la configuration. C'est un objet où chaque clé représente un fichier ou un répertoire de sortie, et la valeur définit ce qui doit être généré.preset: "client"
: Leclient-preset
est un moyen puissant et recommandé de configurergraphql-codegen
pour les applications frontend. Il regroupe plusieurs plugins et offre une expérience simplifiée. Il génère une fonctiongraphql
que vous utiliserez pour écrire vos requêtes.
Étape 4 : Écrire votre première requête GraphQL
Maintenant que graphql-codegen
est configuré, écrivons une requête GraphQL pour récupérer nos articles de blog. Créez un nouveau fichier 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;
Notez que nous importons une fonction gql
à partir du fichier généré src/gql/gql.ts
. C'est la fonction gql
fournie par le client-preset
et c'est ce qui permet la magie de l'inférence de type.
Étape 5 : Exécuter graphql-codegen
et voir la magie
Maintenant, exécutez le script codegen
à partir de votre package.json
:Bash
npm run codegen
Cette commande introspectera le schéma, trouvera votre requête GET_POSTS
et générera les types TypeScript correspondants dans le répertoire src/gql
.
Si vous inspectez maintenant l'objet data
retourné par le hook useQuery
dans Posts.tsx
, vous verrez qu'il est entièrement typé ! Votre IDE fournira l'autocomplétion pour data.allFilms.films
, et TypeScript vous avertira si vous essayez d'accéder à un champ qui n'existe pas dans la requête.
Approfondissement : Un exemple pratique de frontend de blog
Développons notre exemple pour consolider votre compréhension. Imaginez que notre blog ait un schéma plus traditionnel :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!
}
Supposons que ce schéma fonctionne sur http://localhost:4000/graphql
. Nous mettrions à jour notre codegen.ts
en conséquence :TypeScript
// codegen.ts
// ...
schema: "http://localhost:4000/graphql",
// ...
Maintenant, créons un composant pour afficher un seul article et un autre pour en créer un nouveau.
Récupération d'un seul articleTypeScript
// 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;
Après avoir exécuté npm run codegen
, les types pour la requête GetPostQuery
et ses variables seront générés, offrant une sécurité de type pour le hook useQuery
et son résultat.
Création d'un nouvel articleTypeScript
// 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;
Ici, graphql-codegen
génère les types pour la mutation CreatePostMutation
et ses variables. Cela garantit que lorsque vous appelez la fonction createPost
, vous passez les types corrects pour title
, content
et authorId
.
Concepts avancés et meilleures pratiques
À mesure que vous vous familiariserez avec graphql-codegen
, vous rencontrerez des fonctionnalités plus avancées et des meilleures pratiques :
- Fragments :
graphql-codegen
prend en charge de manière excellente les fragments GraphQL. Vous pouvez définir des fragments dans vos fichiers.tsx
etgraphql-codegen
gérera correctement les types, favorisant des dépendances de données réutilisables et colocalisées pour vos composants. - Utilisation de fichiers
.graphql
: Pour une meilleure séparation des préoccupations, vous pouvez écrire vos requêtes, mutations et fragments GraphQL dans des fichiers.graphql
dédiés. Il suffit de mettre à jour le tableaudocuments
dans votrecodegen.ts
pour inclure cette extension de fichier :documents: ["src/**/*.tsx", "src/**/*.graphql"]
. - Scalaires personnalisés : Si votre schéma GraphQL utilise des scalaires personnalisés (par exemple,
Date
,JSON
), vous pouvez les mapper aux types TypeScript correspondants dans votre fichiercodegen.ts
pour maintenir la sécurité des types. - Mode "Watch" : Pour une expérience de développement fluide, vous pouvez exécuter
graphql-codegen
en mode "watch". Cela régénérera automatiquement vos types chaque fois que vous enregistrez un fichier contenant une opération GraphQL. Il suffit d'ajouter un flag--watch
à votre scriptcodegen
danspackage.json
:"codegen": "graphql-codegen --watch"
.
Dépannage des problèmes courants
Bien que graphql-codegen
soit un outil puissant, vous pourriez rencontrer quelques problèmes courants en tant que débutant :
- "Unable to find schema" : Cette erreur signifie généralement que le chemin
schema
dans votrecodegen.ts
est incorrect ou que le serveur GraphQL ne fonctionne pas à l'adresse spécifiée. - Erreurs de configuration de plugin : Assurez-vous d'avoir installé tous les plugins nécessaires et que leurs configurations dans
codegen.ts
sont correctes. - Problèmes de dépendance pair
graphql
: Assurez-vous d'avoirgraphql
installé comme dépendance directe dans votre projet.
Conclusion : Embrassez l'avenir de la sécurité des types
graphql-codegen
est plus qu'un simple outil de génération de code ; c'est un changement de paradigme dans la façon dont nous construisons des applications avec GraphQL. En adoptant l'automatisation et en tirant parti de la puissance de votre schéma, vous pouvez créer des bases de code plus robustes, maintenables et agréables à utiliser.
Ce tutoriel vous a fourni une base solide pour démarrer avec graphql-codegen
. Nous avons couvert les concepts clés, parcouru un exemple pratique et abordé les meilleures pratiques. Le voyage ne s'arrête pas ici. L'écosystème graphql-codegen
est vaste, avec une riche collection de plugins qui répondent à divers frameworks et cas d'utilisation. Je vous encourage à explorer la documentation officielle, à expérimenter différents plugins et à découvrir comment graphql-codegen
peut révolutionner votre flux de travail de développement GraphQL. Bon codage !
Vous voulez une plateforme intégrée, tout-en-un, pour que votre équipe de développeurs travaille ensemble avec une productivité maximale ?
Apidog répond à toutes vos demandes et remplace Postman à un prix beaucoup plus abordable !