Pourquoi Migrer de REST vers GraphQL ?
Le développement moderne demande une interactivité et un temps réaction extrêmement faibles, tout en maintenant une architecture robuste et évolutive. Le protocole REST a longtemps été la solution par défaut pour les interfaces API, offrant des ressources individuelles accessibles via des URL distinctes. Cependant, avec l'émergence de nouvelles exigences et du besoin d'optimiser les performances, le GraphQL est devenu un choix plus performant.
Un cas concret est une application mobile qui nécessite une large gamme de données à la fois, mais sans avoir besoin de toutes ces données lors de chaque requête. Avec REST, cela signifie des multiples appels HTTP vers différentes URL pour récupérer les mêmes données. Par contre, avec GraphQL, on peut effectuer un seul appel HTTP pour obtenir toutes les données nécessaires.
Prerequis
- Connaissance avancée de JavaScript et d'un environnement backend
- Familiarité avec les concepts de RESTful APIs
- Connexion à une base de données SQL ou NoSQL (ex: MongoDB)
- Installation de Node.js et npm
- Outils de développement (VSCode, Postman)
Concepts fondamentaux
Schéma GraphQL
Le schéma GraphQL est le cœur du système. Il définit l'ensemble des types de données disponibles et les relations entre eux.
## Définition du schéma
schema {
query: Query
}
type Query {
task(id: ID!): Task
tasks(status: String): [Task]
}
type Task {
id: ID!
title: String!
status: String!
}
Mutations
Les mutations sont utilisées pour modifier le state de l'application. Elles permettent d'ajouter, mettre à jour ou supprimer des données.
## Mutation pour ajouter une tâche
mutation {
createTask(title: "Nouvelle Tâche", status: "TODO") {
id
title
status
}
}
Résolveurs
Les résolveurs sont les fonctions qui récupèrent les données demandées. Ils sont liés aux champs du schéma.
const resolvers = {
Query: {
task: (_, {id}) => tasks.find(task => task.id === id),
tasks: (_, {status}) => status ? tasks.filter(task => task.status === status) : tasks,
},
Mutation: {
createTask: (_, {title, status}) => {
const newTask = { id: Math.random().toString(), title, status };
tasks.push(newTask);
return newTask;
}
}
}
Mise en pratique : projet fil rouge
Pour illustrer la migration de REST vers GraphQL, nous allons créer une API simple pour un gestionnaire de tâches.
Étape 1 : Initialiser le Projet
mkdir graphql-todo && cd graphql-todo
npm init -y
npm install express express-graphql graphql body-parser cors
Étape 2 : Configurer Express et GraphQL
Créez un fichier server.js :
// Importer les modules nécessaires
const express = require('express');
const { graphqlHTTP } = require('express-graphql');
const bodyParser = require('body-parser');
const cors = require('cors');
// Configuration de l'application Express
const app = express();
app.use(cors());
app.use(bodyParser.json());
// Définition du schéma GraphQL et des résolveurs
const tasks = [
{ id: '1', title: 'Écrire le tutoriel', status: 'DONE' },
{ id: '2', title: 'Lire les livres', status: 'TODO' }
];
const typeDefs = `
schema {
query: Query
mutation: Mutation
}
type Query {
task(id: ID!): Task
tasks(status: String): [Task]
}
type Mutation {
createTask(title: String!, status: String!): Task
}
type Task {
id: ID!
title: String!
status: String!
}
`;
const resolvers = {
Query: {
task: (_, {id}) => tasks.find(task => task.id === id),
tasks: (_, {status}) => status ? tasks.filter(task => task.status === status) : tasks,
},
Mutation: {
createTask: (_, {title, status}) => {
const newTask = { id: Math.random().toString(), title, status };
tasks.push(newTask);
return newTask;
}
}
}
// Configuration de la route GraphQL
app.use('/graphql', graphqlHTTP({
schema: typeDefs,
rootValue: resolvers,
graphiql: true,
}));
// Démarrer le serveur
app.listen(4000, () => {
console.log('Serveur GraphQL en cours sur http://localhost:4000/graphql');
});
Étape 3 : Tester l'API
Ouvrez Postman et accédez à http://localhost:4000/graphql. Vous devriez pouvoir exécuter des requêtes comme :
query {
tasks(status: "DONE") {
id
title
status
}
}
Et créer une nouvelle tâche avec la mutation :
mutation {
createTask(title: "Lire un autre livre", status: "TODO") {
id
title
status
}
}
Erreurs frequentes et debugging
Erreur : "Cannot read property 'id' of undefined"
Code incorrect :
const task = tasks.find(task => task.id === id); return task;Code correct :
const task = tasks.find(task => task.id === id); if (!task) { throw new Error('Task not found'); } return task;Erreur : "SyntaxError: Unexpected token M in JSON at position 0"
Code incorrect :
const data = JSON.parse(req.body.query);Code correct :
const data = req.body.query ? JSON.parse(req.body.query) : {};Erreur : "Cannot read property 'toString' of undefined"
Code incorrect :
const newTask = { id: Math.random().toString(), title, status };Code correct :
const newTaskId = Math.random().toString(); const newTask = { id: newTaskId, title, status }; tasks.push(newTask); return newTask;
Pour aller plus loin
Intégration avec Apollo Client : Utilisez Apollo Client pour gérer le state de votre application React.
Authentication et Authorization : Ajoutez des fonctionnalités d'authentification et d'autorisation pour sécuriser votre API GraphQL.
Performance Optimization : Explorez les techniques de pagination, de sous-requêtes et de lazy loading pour améliorer la performance de votre API.
Défi pratique
Créez une API de blog simple en utilisant GraphQL. Elle devrait permettre de récupérer des articles, des commentaires associés à chaque article et d'ajouter de nouveaux articles ou commentaires.