Anthony Giniers
@antogyn
@aginiers
GraphQL part 2 :
wip
https://slides.com/antogyn/graphql
Bastien Chares
@charesbast
@papybastou
GraphQL, c'est quoi déjà ?
GraphQL est un langage de requête pour des données de type graphe
Facebook, GitHub, Pinterest, Coursera, Shopify, Yelp...
- Hiérarchique
- Fortement typé
- Product Centric : Requêtes côté client
- Rétrocompatible
{
"user": {
"id": 123,
"name": "Tony"
}
}
{
user(id: 123) {
id,
name,
}
}
type User {
id: Int
name: String
}
type Query {
user(id: Int): User
}
type User {
id: Int
name: String @deprecated
identity: Identity
}
type Identity {
name: String
}
{
__schema {
types {
name
fields {
name
type {
name
}
}
}
}
}
- Introspectif
- Fortement typé
{
user(id: 123) {
id,
name,
profilePicture(size: SMALL) {
uri
}
}
}
type Query {
user(id: Int): User
}
type User {
id: Int!
name: String
profilePicture(size: Size): Media
}
type Media {
uri: String
}
enum Size {
SMALL
LARGE
}
- Product Centric
Les spécifications sont encodées dans le client
Le langage de requête répond aux besoins des vues et des ingénieurs front-ends
- Rétrocompatible
{
user(id: 123) {
id,
name,
}
}
type User {
id: Int
name: String @deprecated
identity: Identity
}
type Identity {
name: String
}
{
user(id: 123) {
id,
identity {
name
}
}
}
type User {
id: Int
name: String
}
- Introspectif
{
"__schema": {
"types": [
{
"name": "User",
"fields": [
{
"name": "id",
"type": {
"name": "Int"
}
},
{
"name": "name",
"type": {
"name": "String"
}
},
{
"name": "profilePicture",
"type": {
"name": "Media"
}
}
]
}
...
]
}
}
type User {
id: Int
name: String
profilePicture: Media
}
{
__schema {
types {
name
fields {
name
type {
name
}
}
}
}
}
Et si on codait un réseau social ?
Fastoche non ?
Bah non
- Hiérarchique
Je veux récupérer le dernier post de mon dernier ami
{
me {
friends(last: 1) {
posts(last: 1) {
body
}
}
}
}
{
"me": {
"friends": [{
"posts": [{
"body": "poudre 2 perlimpinpin",
}],
}]
}
}
- GET /me/friends?last=1
- GET /users/:id/posts?last=1
En REST ?
GET /me/friends/posts?last_friends=1&last_posts=1 ??
- Fortement typé
{
user(id: 123) {
id,
name,
profilePicture(size: SMALL) {
uri
}
}
}
type Query {
user(id: Int): User
}
- Outils qui valident nos queries pendant le développement
- Garanties sur la forme et la nature de la réponse
type User {
id: Int!
name: String
profilePicture(size: Size): Media
}
type Media {
uri: String
}
enum Size {
SMALL
LARGE
}
query {
user(id: 123) {
id,
name,
profilePicture(size: SMALL) {
uri
}
}
}
{
user(id: 123) {
id,
name,
profilePicture(size: SMALL) {
uri
}
}
}
- Requêtes construites par le client
Les spécifications sont encodées dans le client
Centré sur le produit (“product centric”)
Le langage de requête répond aux besoins des vues et des ingénieurs front-ends
- Rétrocompatible
{
user(id: 123) {
id,
name,
}
}
type User {
id: Int
name: String @deprecated
identity: Identity
}
type Identity {
name: String
}
{
user(id: 123) {
id,
identity {
name
}
}
}
type User {
id: Int
name: String
}
- Introspectif
{
"__schema": {
"types": [
{
"name": "User",
"fields": [
{
"name": "id",
"type": {
"name": "Int"
}
},
{
"name": "name",
"type": {
"name": "String"
}
},
{
"name": "profilePicture",
"type": {
"name": "Media"
}
}
]
}
...
]
}
}
type User {
id: Int
name: String
profilePicture: Media
}
{
__schema {
types {
name
fields {
name
type {
name
}
}
}
}
}
Le typage fort et cette capacité d'introspection permet l'intégration d'outils puissants
- Génération d'interfaces fortement typées à partir d'un schéma GraphQL
- Découverte et navigation d'API
- Clients externes intelligents
→ GraphiQL
Par exemple :
- Récupérer mes 5 derniers repositories publics
- Afficher leur dernière pull request
- Ajouter un commentaire à une pull request
Queries vs Mutations
Le verbe http n'a pas d'importance avec GraphQL (généralement, on utilise du POST)
Cependant, on distingue les Queries des Mutations (équivalents de Query/Command du CQRS)
type Query {
user(id: String!): User
}
type Mutation {
createUser(name: String!): User
}
query {
user(id: 123) {
id,
name
}
}
mutation {
createUser(name: "toto") {
id,
name
}
}
mutation createToto {
createUser(username: "toto") {
id
}
}
mutation createAnyUser($username: String!) {
createUser(username: $username) {
id
}
}
{
"username": "toto"
}
Variables
=> Requêtes statiques réutilisables
Variable $username
de type String!
➡ /users/antogyn/repos?sort=pushed&direction=desc&page=1
Et en REST ?
https://api.github.com/
Récupérer les 5 derniers repos :
La dernière pull request :
➡ /repos/antogyn/xke-graphql-github/pulls&page=1
Rajouter un commentaire :
➡ /repos/antogyn/xke-graphql-github/issues/3/comments
x5 !!!
Quand utiliser GraphQL ?
- Des données en graphe
- API consommée par du front
- Besoin de limiter le nombre de connections côté client (=mobile)
- Utilisation d'une lib client reconnue (notamment à cause du cache)
- Régulièrement des nouveaux besoins front
Bonus points :
Pain points
- Authentification
- File upload
Et c'est compliqué à mettre en place ?
Non.
(petit temps d'adaptation, mais le gain de temps et de confort en vaut la peine)
Merci !
Questions ?
wip
By antogyn
wip
wip
- 945