GraphQL workshop
Principe de GRAPHQL
RAPPELS
Une spécification de communication pour API
Made in Facebook
Créé en 2012
Publié en 2015
Over HTTP, typé Fortement
Le client decide DE ce qu'il veut récupérer
Pourquoi l'avoir créé
REST :
- Trop de requête
- Trop lourd
RPC :
- Trop spécialisé pour chaque écran
- Pas de cache
Pourquoi l'avoir créé
- Mettre à disposition la bonne quantité de donné pour chaque device
- Alléger les échanges
- Faciliter la mise à disposition de donnée pour différentes versions de client.
Quelques
CONCEPTS
CLés
QUelques concepts clés
- Une API GraphQL n'a qu'un seul end-point (une url)
- On communique uniquement en POST
- Pour définir la structure d'une API GraphQL on définie un schéma
type Project {
name: String
tagline: String
contributors: [User]
}
{
project(name: "GraphQL") {
tagline
}
}
{
"project": {
"tagline": "A query language for APIs"
}
}
Describe your data
Ask for what you want
Get predictable results
github.com/mbreton/graphql-workshop
Rdv à cette adresse :
Lisez le readme jusqu'au chapitre "Exercice"
Familliarisation avec GraphQL
Excercice n°1
localhost:3001/graphQL
GraphiQL : Outil de visualisation/manipulation d'une API GraphQL
server/route/graphql.js
Contient la déclaration de l'API GraphQL.
const Router = require("express").Router;
const graphqlHTTP = require("express-graphql");
const { makeExecutableSchema } = require("graphql-tools");
const service = require("../service");
const router = Router();
const typeDefs = `
type Post {
id: ID!
title: String!
content: String!
}
`;
const resolvers = {};
router.use(
graphqlHTTP({
schema: makeExecutableSchema({ typeDefs, resolvers }),
graphiql: true
})
);
module.exports = router;
End-point GraphQL
Un end-point GraphQL contient le schéma qui déclare l'API et la manière d'interagir avec.
Il contient les resolvers, responsables d'exécuter les comportements attachées correspondant à l'API. (rootValue)
const Router = require("express").Router;
const graphqlHTTP = require("express-graphql");
const { makeExecutableSchema } = require("graphql-tools");
const service = require("../service");
const router = Router();
const typeDefs = `
type Post {
id: ID!
title: String!
content: String!
}
`;
const resolvers = {};
router.use(
graphqlHTTP({
schema: makeExecutableSchema({ typeDefs, resolvers }),
graphiql: true
})
);
module.exports = router;
server/route/graphql.js
le schéma correspond à la déclaration de l'API GraphQL.
Actuellement, seulement le type d'objet Post est déclaré
Les types sont omniprésents :
const Router = require("express").Router;
const graphqlHTTP = require("express-graphql");
const { makeExecutableSchema } = require("graphql-tools");
const service = require("../service");
const router = Router();
const typeDefs = `
type Post {
id: ID!
title: String!
content: String!
}
`;
const resolvers = {};
router.use(
graphqlHTTP({
schema: makeExecutableSchema({ typeDefs, resolvers }),
graphiql: true
})
);
module.exports = router;
TRois TYPES PRINCIPAUX
type permet de déclarer la forme des modèles qu'on manipule
les requêtes pour récupérer les données : Query
et les actions pour transformer les données : Mutation
const typeDefs = `
type User {
fistnames: [String]
lastname: String!
age: Int
gender: Gender!
}
enum Gender {
FEMALE
MALE
OTHER
}
type Query {
users : [User]
}
type Mutation {
createUser(UserInput): User
}
`);
Les resolvers
Leur nom doit correspondre à une Query, ou une Mutation
La fonction resolver sera exécutée à l'appel de type correspondant.
const resolvers = {
Query: {
users (parentValue, args, context) {
return [
{firstnames: ['Winston', 'Leonard', 'Spencer'] /*...*/},
{firstnames: ['Nelson ', 'Rolihlahla '] /*...*/}
];
}
}
};
router.use(
graphqlHTTP({
schema: makeExecutableSchema({ typeDefs, resolvers }),
graphiql: true
})
);
retour à l'exercice 1
GraphQL, PARTIE CLIENT
Excercice n°2
Les articles sont disponibles
Comment y avoir accès en dehors ?
GRAPHQL reste du HTTP
curl -X POST \
-H "Content-Type: application/json" \
-d '{"query": "{ posts { id title } }"}' \
http://localhost:3001/graphql
Dummy with axios
const result = await axios.post("/graphql", { query : `{ users { lastnames } }` });
console.log(result);
/*
{
data : {
data : {
users : [
{firstnames: ['Winston', 'Leonard', 'Spencer']},
{firstnames: ['Nelson ', 'Rolihlahla ']}
]
}
}
}
*/
retour à l'exercice 2
Création d'un Comment via GraphQL
Excercice n°3
Operation Name
Pour nommer les requêtes envoyées à une API GraphQL.
Très utile pour débugger et pour la lisibilité du code
query getPosts {
posts {
id
title
content
}
}
Argument
Paramètre d'entré d'une Query GraphQL
posts(id:"abc1234") {
title
content
}
Variables
Variable typée d'une opération
query getPostById($id: ID!){
posts(id: $id) {
title
content
}
}
Variable
Paramètre
MUtations
La Mutation, et très semblable à la Query car elle représente une opération executable sur le graph.
Par convention
Mutation = modification
Query = lecture
type Mutation {
createUser(UserInput): User
}
MUtations
Comme les Query, on doit lui fournir un resolver correspondant
const resolvers = {
Mutation: {
createUser(parentValue, args) {
return addNewUser(args);
}
}
};
retour à l'exercice 3
Création d'un Post via GraphQL
Excercice n°4
Input TYPE
Fait pour représenter des objets complexes en paramètre de mutation
const typeDefs = `
type User {
id: ID!
fistnames: [String]!
lastname: String!
age: Int
}
input UserInput {
fistnames: [String]!
lastname: String!
age: Int
}
type Mutation {
createUser(UserInput): User
}
`);
retour à l'exercice 4
Conclusion
Vous savez faire un CRUD en GraphQL
Pour les projets de plus grande envergure Apollo devient vite nécessaire
Peu de désavantage comparé à REST, excepté le caching encore dure à gérer finement, et reste moins utilisé par la majorité.
Merci
GraphQL workshop
By Mathieu Breton
GraphQL workshop
- 1,832