Dans un projet web, lorsqu’on parle API (Application Programming Interface), nous vient souvent en tête REST (Representational State Transfer). Et pour cause, ce style d’architecture, né dans les années 2000, et devenu une norme, presque un pré-requis, à tout développement web utilisant du back-end.
Cependant, REST n’est pas la seule solution technique lorsqu’on définit la stack technique de son projet. Son plus gros adversaire est GraphQL, et il a des arguments en sa faveur !
Qu’est ce que GraphQL ? Comment cette techno fonctionne ? Quels en sont les avantages et les inconvénients ?
Toutes les réponses dans cet article !
GraphQL : introduction
GraphQL (pour Graph Query Language) est un langage de requête et un environnement d’exécution. Tout comme le célèbre framework front React, Flux (concurrent du pattern MVC) et d’autres encore, cette techno est sortie des labos de Facebook, en 2012. Elle fut par la suite publiée en projet open-source en 2015.
Pour en faire une définition simple, en une phrase, on pourrait dire que, contrairement à REST, c’est la requête du client qui définit la structure des données qui lui seront rendues.
Mais nous allons détailler cela par la suite.
Fonctionnement
Comme on vient de le dire, avec GraphQL, c’est le client qui décide précisément des données qui lui seront rendues.
Concrètement, avec REST on définit une requête via un verbe (GET, POST, PUT, DELETE, PATCH) et des éventuels paramètres (dans le body ou dans l’url). Avec GraphQL, on oublie ce mode de fonctionnement. À la place, toutes les requêtes sont des POST, et prennent en attribut une structure de données (avec ou sans facteurs discriminants, comme des ids), définissant ce que l’API doit lui retourner.
Nous allons détailler ce mode de fonctionnement dans la section suivante.
La requête GraphQL
Donc, une requête client GraphQL envoie une structure de données. Cette structure de données, c’est tout simplement un Objet, qui contient les noms des attributs qu’il souhaite recevoir en retour.
Prenons l’exemple du site d’un fournisseur de fruits et légumes ayant adopté l’architecture GraphQL.
Au niveau logique, il possède deux models, Product et Order, définis par GraphQL comme ceci (on reviendra sur la structure plus tard) :
Pour récupérer des éléments de la base de données de ce fournisseur, le front pourrait envoyer dans sa requête :
Il récupérerait dans ce cas :
À savoir que, comme c’est le front qui décide de la structure de retour, la requête aurait pu contenir les clés de l’objet dans un ordre différent (tout en respectant l’architecture de l’objet) ainsi qu’omettre certains champs ; le back s’y serait adapté et aurait servi la structure demandée.
L’API GraphQL
Une API GraphQL s’organise autour de données Types et Champs. Concrètement, le squelette d’une API GraphQL peut contenir trois Types d’objet différent : Query, Mutation, ainsi que la définition des models de la base de données.
Voici un exemple de squelette d’API GraphQL :
Le premier type du schéma, Query, contient toutes les requêtes acceptées par l’API. Une fois la requête reçue depuis le front, l’objet Query permet de vérifier qu’elle, ou du moins son format, est permise par l’API.
Les deux autres objets que l’on voit sur le schéma, Product et Order, sont tout simplement les définitions des structures de ces models. En clair, on y définit tous les champs que le front va pouvoir demander. Comme déjà expliqué, il n’est pas obligé de récupérer tous les champs, il n’obtient que ce qu’il demande – c’est là tout l’intérêt de GraphQL ; on en reparlera.
Le troisième Type, non représenté ici car lui non obligatoire, est la Mutation. Dans l’objet global Mutation, on définira toutes les actions possibles qui permettront de faire des modifications sur le ou les modèles définis. Par exemple, toujours dans le cas du fournisseur de fruits et légumes, on pourrait avoir une mutation « createProduct ».
Les avantages de GraphQL
Comme on l’a dit, l’intérêt principal de GraphQL est d’avoir entièrement la main, depuis le front, sur les données retournées par l’API.
En plus d’avoir un flux personnalisé et personnalisable, cela permet surtout d’éviter l’under-fetching et l’over-fetching. Définissons ce que sont ces problématiques résolues par GraphQL.
L’under-fetching
Comme son nom l’indique, l’under-fetching, c’est le fait de ne pas récupérer assez de données via une API.
Pour bien comprendre, reprenons le schéma montré plus haut contenant la réponse à une requête GraphQL, en rajoutant les données de l’utilisateur connecté :
Comme on le voit, on récupère un order (mais cela peut être un ensemble d’orders) contenant une liste (productsList), contenant elle-même un ensemble de produits (product) – un seul dans cet exemple ; ainsi que les données d’un utilisateur connecté.
Cela pourrait être le type de données récupérées lorsqu’on se rend sur une page d’historique des commandes, par exemple.
Avec une API REST, il est fort possible que nous récupérions uniquement les données de l’utilisateur via un premier appel. Ce qui nous forcerait à faire un deuxième appel serveur pour récupérer les commandes de utilisateur en question.
C’est de l’under-fetching : la première requête ne nous donne pas assez d’informations, ce qui nous force à en faire une deuxième. La multiplication d’appels serveur risque de ralentir le chargement de la page ; GraphQL permet donc une optimisation des flux et du temps de chargement.
La solution avec REST serait de créer une API spécifique pour retourner l’ensemble de ces données. Il est cependant difficile sinon impossible de couvrir l’ensemble des cas d’utilisation. GraphQL a donc ici tout son intérêt.
L’over-fetching
À l’opposé de l’under-fetching, on a l’over-fetching. logiquement, si l’under-fetching ne renvoie pas assez de données, l’over-fetching en renvoie trop.
Pour reprendre l’exemple précédent, on pourrait se dire que notre page web n’a besoin d’afficher que les utilisateurs et les noms des produits commandés ; pas leurs prix ni les quantités.
Une API REST ne laisserait pas le choix : elle retourne tout ce que le back-end lui dit de retourner. Si une même API est appelée à divers endroit d’une application web avec des besoins un peu différents (besoin ou non de certaines données spécifiques), le plus simple et de retourner trop de data plutôt que pas assez. Dans le but d’éviter… L’under-fetching.
Donc, dans le cas présent, on remontera plus de données que ce dont on a besoin : c’est de l’over-fetching. Le principal problème de l’over-fetching, c’est qu’il peut ramener d’énormes quantités de données inutiles et lourdes (des images, par exemple). Cela peut considérablement ralentir une page web, mais aussi augmenter la consommation de data de l’utilisateur. Ce qui peut avoir une importance si ce dernier utilise la webapp depuis son mobile, par exemple.
J’ai moi-même, en tant que développeur, eu à faire à ce genre de problématique. Je travaillais sur une application mobile et devais me connecter à un back-end REST déjà existant. Ce back-end contenait des API qui délivraient déjà des informations à un site web.
Le problème, c’est que l’application mobile avait besoin de beaucoup moins de données que le site web. Je récupérais donc beaucoup trop de données, ce qui augmentait la taille des flux réseaux. La différence était minime, certes, mais multiplié par le nombre d’appels, on peut vite arriver des mégaoctets. Pour l’anecdote, le développeur en charge de l’API a refusé de la modifier ou d’en créer une autre pour mon application.
Il est donc important de penser à ce genre de cas d’utilisation dès l’étape des choix technologiques.
Il est cependant possible d’améliorer une API REST pour éviter l’over-fetching. On peut passer un boolean en paramètre, par exemple, qui différencierait un appel depuis un site ou depuis un mobile, et qui déciderait des données que doit retourner l’API.
Cette solution trouve toutefois ses limites suivant le nombre de cas d’utilisation. GraphQL répond donc là bien aussi à cette problématique : on récupère uniquement ce que l’on demande.
Les inconvénients de GraphQL
Après avoir lu ces avantages vous devez vous dire que GraphQL est un outil magique et qu’il devrait être utilisé partout !
Et ça se tient comme raisonnement. Mais GraphQL possède aussi des défauts.
La mise en cache
Le plus gros d’entre eux, c’est la complexité de la mise en cache. En effet, avec une API REST qui retourne toujours le même format de données, la mise en cache est très facile. Ça limite donc les appels à la base de données, réduisant le temps de requête (problématique que résout aussi GraphQL).
Une API GraphQL n’ayant pas de retour défini, la mise en cache côté serveur est difficile à mettre en place. Si on tient a faire du cache, le plus simple sera d’en faire côté front.
Une montée en compétence
À l’heure actuelle, REST est toujours plus utilisé que GraphQL. C’est typiquement la techno d’API qu’on enseigne en premier, il est donc normal que ça soit celle qui soit mise en place par défaut.
Passer à une autre technologie de développement d’API n’est pas anodin, et REST et GraphQL sont radicalement différents. Apprendre cette techno, et apprendre à l’utiliser proprement, demandera une montée en compétences parfois importante. Les développeurs ou leurs managers n’auront peut-être ni le temps ni l’envie de s’y former.
Même si c’est un faux argument ; c’est du temps qu’on peut au final récupérer sur la charge de développement.
Si vous voulez vous former à GraphQL, vous pouvez vous rendre sur le site officiel, ainsi que sur How To GraphQL.
Conclusion
Comme on l’a vu, GraphQL est une techno concurrente de REST, qui peut avoir ses avantages. Évidemment, elle ne répondra pas à tous les besoins, et dire qu’elle est plus efficiente que REST dans tous les cas d’utilisation serait mentir. Il n’y a pas de bonne ou de mauvaise techno dans ce cas ; cela dépend des besoins.
Avez-vous déjà utilisé GraphQL ? Quels sont vos retours ? N’hésitez pas à les partager en commentaire !