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 :

Utilisons le GraphiQL de GitHub !

 

https://developer.github.com/early-access/graphql/explorer/

 

  • 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 ?