GraphQL

https://goo.gl/uKko8y
 

About me

Frontend Engineer Xing

 

Guitar/Bass player

@matheusrocha89

@matheusrocha

Before the GraphQL

MVC

Mobile market growth.

What now?

REST

fetch('https://api.domain.com/v1/users/123');
...

{
    ...,
    data: {
        id: 123,
        firstName: '...',
        lastName: '...',
        email: '...',
        ...,
    }
}

And if we need more complex data and requests?

Create more endpoints

  • v1/users/123/friends
  • v1/users/123/posts
  • v1/users/123/last-posts
  • v1/users/123/friends/liked-pages
  • v1/users/123/friends/last-liked-pages
  • v1/users/123/friends/last-liked-pages/last-posts
  • v1/users/123/friends/last-liked-pages/posts-friends-liked
  • v1/users/123/friends/last-photos-and-pages-liked
  • v1/users/123/i-dont-have-any-idea-what-the-hell-is-this-anymore

Returns more data than what you really need

Now we have a serious problem

GraphQL comes up

2012

GraphQL is created and used internally by Facebook

2015

GraphQL is released Open Source by Facebook

But what is this GraphQL?

"GraphQL is a query language for your API, and a server-side runtime for executing queries by using a type system you define for your data. GraphQL isn't tied to any specific database or storage engine and is instead backed by your existing code and data."

Advantages?

GraphQL

Client

Backend

GraphQL

Client

Backend

Backend

New mindset

Concepts

Typed

Types

  • Int
  • Float
  • String
  • Boolean
  • ID
  • Enum

But...

Nothing blocks you to create your own data types

type Character {
  name: String!
  appearsIn: [Episode]!
}

Types: Query and Mutation

Query

Mutation

type Query {
  posts: [Post]
  author(id: Int!): Author
}
type Mutation {
  upvotePost(postId: Int!): Post
}

Interfaces

interface Character {
  id: ID!
  name: String!
  friends: [Character]
  appearsIn: [Episode]!
}

type Human implements Character {
  id: ID!
  name: String!
  friends: [Character]
  appearsIn: [Episode]!
  starships: [Starship]
  totalCredits: Int
}

type Droid implements Character {
  id: ID!
  name: String!
  friends: [Character]
  appearsIn: [Episode]!
  primaryFunction: String
}

// Query

query HeroForEpisode($ep: Episode!) {
  hero(episode: $ep) {
    name
    ... on Droid {
      primaryFunction
    }
  }
}

Fragments


fragment comparisonFields on Character {
  name
  appearsIn
  friends {
    name
  }
}

{
  leftComparison: hero(episode: EMPIRE) {
    ...comparisonFields
  }
  rightComparison: hero(episode: JEDI) {
    ...comparisonFields
  }
}

Subscription

// Server
type Subscription {
  postAdded: Post
}


// Client

subscription {
  postAdded {
    id
    title
    content
  }
}

Schema

  type Author {
    id: Int!
    firstName: String
    lastName: String
    posts: [Post] # the list of Posts by this author
  }

  type Post {
    id: Int!
    title: String
    author: Author
    votes: Int
  }

  # the schema allows the following query:
  type Query {
    posts: [Post]
    author(id: Int!): Author
  }

  # this schema allows the following mutation:
  type Mutation {
    upvotePost (
      postId: Int!
    ): Post
  }

OK! I define my graph but... how does it know where to get the data?

Resolvers

Resolver's parameters

  • parent / root
  • args
  • context
  • info
import { find, filter } from 'lodash';

// example data
const authors = [
  { id: 1, firstName: 'Tom', lastName: 'Coleman' },
  { id: 2, firstName: 'Sashko', lastName: 'Stubailo' },
];
const posts = [
  { id: 1, authorId: 1, title: 'Introduction to GraphQL', votes: 2 },
  { id: 2, authorId: 2, title: 'Welcome to Meteor', votes: 3 },
];

const resolvers = {
  Query: {
    posts: () => posts,
    author: (_, { id }) => find(authors, { id: id }),
  },
  Mutation: {
    upvotePost: (_, { postId }) => {
      const post = find(posts, { id: postId });
      if (!post) {
        throw new Error(`Couldn't find post with id ${postId}`);
      }
      post.votes += 1;
      return post;
    },
  },
  Author: {
    posts: (author) => filter(posts, { authorId: author.id }),
  },
  Post: {
    author: (post) => find(authors, { id: post.authorId }),
  },
};

But...

Besides what I told

  • Dataloader (batching, caching).
  • Authorization.
  • Metadata that can be used.
  • Freedom to create pagination 
  • Validation

Don't forget: Facebook uses GraphQL

So... it's ready

Advantages of GraphQL against REST

No more over/under fetching

The product evolves faster

Where I can learn more

  • http://graphql.org/
  • https://www.howtographql.com/
  • https://services.github.com/on-demand/graphql/
  • https://github.com/blog/2412-learn-graphql-with-github
  • https://medium.com/netflix-techblog/our-learnings-from-adopting-graphql-f099de39ae5f
  • https://principledgraphql.com/

Tools / Interesting links

GraphiQL

http://graphql.org/swapi-graphql/

https://developer.github.com/v4/explorer/

https://github.com/matheusrocha89/graphql-with-firestore-example

https://github.com/matheusrocha89/graphql-camara-deputados

Graphile - https://www.graphile.org/

Servers GraphQL

NodeJS, PHP, Ruby, Go, Java, Elixir, Erlang, Groovy, Scala, Clojure, C#, Python...

Clients GraphQL

NodeJS, Javascript, Go, C#, Java (Android), Swift/Objective-C, Python.

Who uses?

More

Example

Thanks

GraphQL - English

By Matheus Cruz Rocha

GraphQL - English

Presentation about GraphQL

  • 677