Upgrade to Pro — share decks privately, control downloads, hide ads and more …

REST in Peace

REST in Peace

Introduction to GraphQL and lessons learned.

Avatar for Nicolas Dular

Nicolas Dular

June 06, 2018

Other Decks in Programming

Transcript

  1. What is GraphQL? • Developed by Facebook 
 (started in

    2012, open source since 2015) • A declarative query language for APIs • Single Endpoint for all requests
  2. Comparison to REST GET /users PUT /users/:id POST /users DELETE

    /users/:id GET /users/todos GET /users_with_all_todos GET /users_with_all_friends POST /api/graphql BODY
 { query: “users { name }” } REST GraphQL
  3. • Core Concepts • Live Demo • Practical Tips •

    Lessons Learned • Summary Agenda
  4. Core Concepts Types, Queries, Mutations & Subscriptions Receive Data through

    Queries Write Data with Mutations Real Time Updates with Subscriptions
  5. type User { id: ID! name: String! age: Number! todos:

    [Todo!]! } Core Concepts The Schema Definition Language (SDL) type Todo { id: ID! text: String! description: String }
  6. type User { id: ID! name: String! age: Number! todos:

    [Todo!]! } type Todo { id: ID! text: String! description: String } Core Concepts The Schema Definition Language (SDL) Optional Field Referencing ID is a special type ! Required Field
  7. Core Concepts query AllUsersQuery { users { id name todos

    { id text } } } { "data": { "users": [ { "id": "1", "name": "Jon Snow", "todos": [ { "id": "1", "text": "Get the dragons back" }, { "id": "2", "title": "Fight the Night King" } ] } ] } } Query Output / Response Queries / Request all users
  8. Core Concepts Mutations type Mutation { addUser(name: String!, age: Number!):

    User! updateTodo(id: ID!, updatedText: String!): Todo! }
  9. Core Concepts Mutations / Update Todo mutation UpdateTodo { updateTodo(

    id: "1" updatedText: "Get the dragons back from the Night King" ) { id text } } { "data": { "updateTodo": { "id": "1", "text": "Get the dragons back from the Night King", } } } Mutation Output / Response
  10. • Core Concepts ✅ • Live Demo • Practical Tips

    • Lessons Learned • Summary Agenda
  11. • Core Concepts ✅ • Live Demo ✅ • Practical

    Tips • Lessons Learned • Summary Agenda
  12. Practical Tips Mutation Structure mutation addUser(input: AddUserInput!): AddUserPayload input AddUserInput

    { name: String! age: Number } type AddUserPayload { result: User errors: [Error!]! } type Error { field: String! message: String! }
  13. Practical Tips Mutation Structure mutation addUser(input: AddUserInput!): AddUserPayload input AddUserInput

    { name: String! age: Number } type AddUserPayload { result: User errors: [Error!]! } Required Input Optional Response Separate input for each mutation Separate payload for each mutation with same schema type Error { field: String! message: String! }
  14. Practical Tips Treat (validation) errors as data { "data": {

    ... }, "errors": [ ... ] } Standard GraphQL JSON Response What we want { "data": { { "result": null, "errors": [ { "field": "name", "message": "can not be empty” } ] } }, "errors": [ ] } Treat validation errors as data Network, Permission Errors etc.
  15. Practical Tips Make Mutations explicit mutation markTodoAsDone(id: ID!): MarkTodoAsDonePayload! Use

    “Actions” instead of forcing yourself to CRUD mutations. Recommended: https://medium.com/@__xuorig__/graphql-mutation-design-anemic-mutations-dd107ba70496
  16. Practical Tips Search with union types Searching for different types

    in one query? type Query { search(term: String!): User | Todo } search(term: "Night King") { ... on User { id, name } ... on Todo { id, text, description } }
  17. Practical Tips Search on Nodes Can also be solved with

    inheritance type Query { search(term: String!): [Node] } interface Node { id: ID! } type User implements Node { name: String! } type Todo implements Node { text: String! }
  18. Practical Tips File Uploads You can define your own Scalars

    and resolve them how you want. mutation upload(file: Upload!): UploadPayload! Here, file can just be a String that references the name of the actual file in a multipart/form-data request.
  19. Practical Tips Authentication Token based authentication and in the end

    just another mutation. mutation authenticate(input: AuthInput!): AuthPayload input AuthInput { email: String! password: String! } type AuthPayload { token: String! errors: [Error!]! } Token for future authentication as Auth Header
  20. Practical Tips Libraries Apollo Relay • Simple API • iOS/Android

    Libraries • Caching works, but requires manual effort (e.g. no solution for deletion yet) • Optimised for efficent communication with the Server • Complex API compared to Apollo
  21. Practical Tips N+1 Queries DataLoader Generic Data Fetching utility 


    to reduce requests by only running
 a single query. currentUser { todos { description attachments { name sharedWith { name } } } }
  22. • Core Concepts ✅ • Live Demo ✅ • Practical

    Tips ✅ • Lessons Learned • Summary Agenda
  23. Lessons Learned Not everything is a root query • Think

    in Graphs! Do not create a query for everything • Think about scope currentUser { todos { text } } allTodos { text } User todos? Organisation todos? Application todos?
  24. Lessons Learned Use Relay’s mutation & type structure • Relay

    is an opinionated GraphQL Schema • Everything inherits from Node • Every mutation has a separate Input and Payload type • Solves pagination with cursors and global IDs
  25. Lessons Learned The GraphQL Schema is not your UI •

    Sounds obvious, but don’t put render logic (like a calendar) in your schema • GraphQL API shouldn’t be opinionated about your UI. This will lead to less breaking changes
  26. Lessons Learned Remove every REST endpoint • No authentication via

    REST • No File upload via REST • Makes your life easier - especially with caching in Apollo/Relay (Note: Apollo can now deal with GraphQL and REST APIs)
  27. • Core Concepts ✅ • Live Demo ✅ • Practical

    Tips ✅ • Lessons Learned ✅ • Summary Agenda
  28. Summary Why you want to move to GraphQL • Your

    type system is your documentation • Only download what you need (at least in theory) • Remove logic from the clients
  29. Summary Downsides • N+1 Queries and Caching - but this

    Problem can be solved • There are no cons, except when you already have a REST API. • Apollo supports using REST APIs + GraphQL APIs at the same time • You can wrap your REST API with GraphQL