$30 off During Our Annual Pro Sale. View Details »

GraphQL with JavaScript

GraphQL with JavaScript

My GraphQL presentation from JSTalks

Radoslav Stankov

November 15, 2015
Tweet

More Decks by Radoslav Stankov

Other Decks in Programming

Transcript

  1. Implementing GraphQL with
 JavaScript Radoslav Stankov 21/10/2015

  2. Radoslav Stankov @rstankov http://rstankov.com
 http://blog.rstankov.com http://github.com/rstankov

  3. None
  4. None
  5. None
  6. None
  7. None
  8. None
  9. GET /api/posts?date=2015-10-31 { id: 1, title: "Post title", tagline: "Post

    headline", votes_count: 1, comments_count: 1, url: '/category/slug', thumbnail_url: 'assets.producthunt.com/uuid', hunter_id: 1 }
  10. None
  11. None
  12. GET /api/users/1 { id: 1, name: 'User Name', handle: 'user_name',

    avatar_url: 'assets.producthunt.com/uuid' }
  13. Rest Client Rest Server

  14. Rest Client Rest Server /api/posts?date=2015-10-31

  15. Rest Client Rest Server /api/posts?date=2015-10-31 /api/users/{x} (for X users)

  16. Rest Client Rest Server /api/posts?date=2015-10-31 /api/users/{x} (for X users)

  17. …approach 2

  18. GET /api/posts?date=2015-10-31 { id: 1, title: "Post title", tagline: "Post

    headline", votes_count: 1, comments_count: 1, url: '/category/slug', thumbnail_url: 'assets.producthunt.com/uuid', hunter: { id: 1, name: 'User Name', handle: 'user_name', avatar_url: 'assets.producthunt.com/uuid' } }
  19. None
  20. None
  21. None
  22. None
  23. None
  24. None
  25. GET /api/posts?date=2015-10-31 { id: 1, title: "Post title", tagline: "Post

    headline", votes_count: 1, comments_count: 1, url: '/category/slug', thumbnail_url: 'assets.producthunt.com/uuid', hunter: { id: 1, name: 'User Name', handle: 'user_name', avatar_url: 'assets.producthunt.com/uuid' }, makers: [{ id: 2, name: 'Second User', handle: 'second_user', avatar_url: 'assets.producthunt.com/uuid' }] }
  26. None
  27. None
  28. None
  29. GET /api/posts?date=2015-10-31 { id: 1, title: "Post title", tagline: "Post

    headline", votes_count: 1, comments_count: 1, url: '/category/slug', thumbnail_url: 'assets.producthunt.com/uuid', hunter: { id: 1, name: 'User Name', handle: 'user_name', avatar_url: 'assets.producthunt.com/uuid' }, makers: [{ id: 2, name: 'Second User', handle: 'second_user', avatar_url: 'assets.producthunt.com/uuid' }], platform: [{ name: 'iPhone', }, { name: 'Mac', }, { name: 'Web', }] }
  30. None
  31. None
  32. …approach 3

  33. None
  34. Rest Client Rest Server

  35. Rest Client Rest Server endpoint 1 feature 1

  36. Rest Client Rest Server endpoint 1 feature 1 endpoint 2

    feature 2
  37. Rest Client Rest Server endpoint 1 feature 1 endpoint 2

    feature 2 endpoint 3 feature 3
  38. Rest Client Rest Server endpoint 1 feature 1 endpoint 2

    feature 2 endpoint 3 feature 3 endpoint N feature N
  39. None
  40. None
  41. None
  42. None
  43. None
  44. None
  45. { id: 1, title: "Post title", tagline: "Post headline", votes_count:

    1, hunter: { id: 1, avatar_url: 'assets.producthunt.com/uuid' }, makers: [{ id: 2, avatar_url: 'assets.producthunt.com/uuid' }] }
  46. { id title tagline votes_count hunter { id avatar_url }

    makers { id avatar_url } }
  47. None
  48. GET /graphql Request Body Response Body

  49. 
 query { post(id: 1){ id title tagline votes_count hunter

    { id avatar_url } makers { id avatar_url } } } GET /graphql Request Body Response Body
  50. 
 query { post(id: 1){ id title tagline votes_count hunter

    { id avatar_url } makers { id avatar_url } } } GET /graphql Request Body Response Body
  51. 
 query { post(id: 1){ id title tagline votes_count hunter

    { id avatar_url } makers { id avatar_url } } } GET /graphql Request Body Response Body { "data": { "post": { "id": 1, "title": "title", "tagline": "tagline", "votes_count": 0, "hunter": { "id": 1, "avatar_url": "assets.producthu }, "makers": [ { "id": 1, "avatar_url": "assets.product } ] } } }
  52. It’s that simple

  53. 
 https://facebook.github.io/graphql


  54. GraphQL is a query language created by Facebook in 2012

    which provides a common interface between the client and the server for data fetching and manipulations. The client asks for various data from the GraphQL server via queries.
  55. Architecture 
 GraphQL Library
 (Per-Language)
 
 Type
 Definitions
 
 Application


    Code

  56. GraphQL • Single endpoint • Not just a library •

    Application-Layer Protocol • Server agnostic • Strongly-typed • Client-specified queries • Hierarchical
  57. Tries to solve • N+1 API queries • API response

    bloat • Documentation • Ad Hoc Endpoints • Structure issues
  58. Code var RootQueryType = new GraphQLObjectType({ name: 'RootQueryType', fields: {

    post: { type: PostType, description: 'Find post by id', args: { id: { description: 'Post id' type: new GraphQLNonNull(GraphQLInt) } }, resolve: function(_, params) { return data.posts.find(params.id); } }, });
  59. Code var PostType = new GraphQLObjectType({ name: 'Post', fields: function()

    { return { id: { type: GraphQLInt, }, title: { type: GraphQLString, }, user: { type: UserType, description: "Creator of the post", resolve: function(post) { return data.users.find(post.user_id); } }, }; } });
  60. Code var [TYPE] = new GraphQLObjectType({ name: [NAME],
 description: [DESCRIPTION],

    fields: function() { return { [FIELD_NAME]: { description: [DESCRIPTION], deprecation: [DEPRECATION MARKER], type: [TYPE],
 args: [LIST OF FIELD ARGUMENT],
 resolve: [FUNCTION] }, } } });
  61. Code var PostType = new GraphQLObjectType({ name: 'Post', fields: function()

    { return { id: { type: GraphQLInt,
 resolve: function(post) { return post.id; } }, user: { type: UserType, resolve: function(post) { return data.users.find(post.user_id); } }, }; } });
  62. Code var PostType = new GraphQLObjectType({ name: 'Post', fields: function()

    { return { id: { type: GraphQLInt }, user: { type: UserType, resolve: function(post) { return data.users.find(post.user_id); } }, }; } });
  63. Query 
 query { post(id: 1){ id title tagline votes_count

    hunter { id avatar_url } makers { id avatar_url } } } { "data": { "post": { "id": 1, "title": "title", "tagline": "tagline", "votes_count": 0, "hunter": { "id": 1, "avatar_url": "assets.producthun }, "makers": [ { "id": 1, "avatar_url": "assets.producth } ] } } }
  64. Mutation 
 mutation { createUser(name: "Rado") { id } }

    { "data": { "createSpeaker": { "id": 2 } } }
  65. Code var RootMutationType = new GraphQLObjectType({ name: 'RootMutationType', fields: {

    createPost: { type: PostType, args: { title: { type: new GraphQLNonNull(GraphQLString) }, tagline: { type: new GraphQLNonNull(GraphQLString) }, user_id: { type: new GraphQLNonNull(GraphQLInt) }, }, resolve: function(_, params) { if (!data.users.find(params.user_id)) { throw "Invalid user id - " + params.user_id; } return data.posts.create(params); }, }, }, });
  66. Documentation 
 query { __schema { types { name fields

    { name type { name kind ofType { name kind } } } } } } { "data": { "__schema": { "types": [ { "name": "Query", "fields": [ { "name": "user", "type": { "name": "Non-Null", "kind": "NON_NULL", "ofType": { "name": "User", "kind": "OBJECT" } } }, { "name": "post", "type": { "name": "Non-Null", "kind": "NON_NULL", "ofType": { "name": "Post", "kind": "OBJECT" } } } ] },
  67. { id hunter: { id name
 small_avatar_url: avatar_url(size: 100)
 big_avatar_url:

    avatar_url(size: 400) } } Cool tricks
  68. Code var UserType = new GraphQLObjectType({ name: 'User', fields: function()

    { return { // ... some field definitions ... picture: { type: GraphQLString, args: { size: { type: GraphQLInt }, }, resolve: function(user, params) { var size = params.size || 400; return 'file.example.com/' + user.picture_uuid + "?size=" + size; } }, }; } });
  69. query withFragments { user(id: 4) { friends(first: 10) { ...friendFields

    } mutualFriends(first: 10) { ...friendFields } } } fragment friendFields on User { id name profilePic(size: 50) } Cool tricks
  70. 
 https://facebook.github.io/react


  71. 
 https://facebook.github.io/relay


  72. None
  73. PostContainer = Relay.createContainer(Post, { fragments: { post: () => Relay.QL`

    fragment on Post { id title tagline votes_count } `, }, }); Relay
  74. Demo

  75. Issues • New, just a draft specification • Mutations are

    weird • Best practices and solutions • Large datasets
  76. None
  77. https://speakerdeck.com/rstankov/introduction-to-graphql

  78. https://github.com/rstankov/talks-code

  79. None
  80. None
  81. @rstankov Thanks :)

  82. Questions?