Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.

JS Fest 2018. Иван Гончаров. W.T.F. is GraphQL?

157 views

Published on

В последнее время очень много хайпа вокруг GraphQL и вас наверное интересует подходит ли он для вашего проекта. В своём докладе я хочу раскрыть суть этой технологии рассказав какие проблемы она решает и как она работает в деталях. Я покажу как писать запросы, посылать их и как они исполняются на сервере. Также, я расскажу про проблемы GraphQL и о том насколько эта технология готова к использованию в продакшене

Published in: Education
  • Be the first to comment

  • Be the first to like this

JS Fest 2018. Иван Гончаров. W.T.F. is GraphQL?

  1. 1. From Back-end to Front-end Kiev 2018 W.T.F. is GraphQL? Ivan Goncharov, APIs.guru
  2. 2. Microsoft: XML-RFC, SOAP, OData Facebook: Thrift, GraphQL Google: gRPC Netflix: Falcorn
  3. 3. What are the problems GraphQL solves?
  4. 4. http://swapi.co/ Now with The Force Awakens data! SWAPI The Star Wars API
  5. 5. GET https://swapi.co/api/people/1/ HTTP/1.0 200 OK Content-Type: application/json { "name": "Luke Skywalker", "height": "172", "mass": "77", "gender": "male", "homeworld": "https://swapi.co/api/planets/1/", "films": [ "https://swapi.co/api/films/2/", ...
  6. 6. https://swapi.co/api/people/1/ SELECT * FROM people WHERE ID = 1
  7. 7. Luke Skywalker Gender: Male | Height: 172cm | Mass: 77kg Homeworld: Tattoine Planetmates: C-3PO Darth Vader Owen Lars R5-D5 Beru Whitesun Iars Biggs Darklighter Shmi Skywlaker Cliegg Lars
  8. 8. https://swapi.co/api/people/1/ { "name": "Luke Skywalker", "height": "172", "mass": "77", "hair_color": "blond", "skin_color": "fair", "eye_color": "blue", "birth_year": "19BBY", "gender": "male", "homeworld": "https://swapi.co/api/planets/1/", "films": [...], "species": [...], ...
  9. 9. https://swapi.co/api/planets/1/ { "name": "Tatooine", "rotation_period": "23", "orbital_period": "304", ... "residents": [ "https://swapi.co/api/people/1/", "https://swapi.co/api/people/2/", "https://swapi.co/api/people/4/", ...
  10. 10. https://swapi.co/api/people/2/ { "name": "C-3PO", "height": "167", "mass": "75", "hair_color": "n/a", "skin_color": "gold", "eye_color": "yellow", "birth_year": "112BBY", "gender": "n/a", "homeworld": "https://swapi.co/api/planets/1/", "films": [ "https://swapi.co/api/films/2/", ...
  11. 11. Problems
  12. 12. { "name": "Luke Skywalker", "height": "172", "mass": "77", "hair_color": "blond", "skin_color": "fair", "eye_color": "blue", "birth_year": "19BBY", "gender": "male", "homeworld": "https://swapi.co/api/planets/1/", "films": [ "https://swapi.co/api/films/2/", "https://swapi.co/api/films/6/", "https://swapi.co/api/films/3/", "https://swapi.co/api/films/1/", "https://swapi.co/api/films/7/" ], "species": [ "https://swapi.co/api/species/1/" ], "vehicles": [ "https://swapi.co/api/vehicles/14/", "https://swapi.co/api/vehicles/30/" ], "starships": [ "https://swapi.co/api/starships/12/", "https://swapi.co/api/starships/22/" ], "created": "2014-12-09T13:50:51.644000Z", "edited": "2014-12-20T21:17:56.891000Z", "url": "https://swapi.co/api/people/1/" } { "name": "Tatooine", "rotation_period": "23", "orbital_period": "304", "diameter": "10465", "climate": "arid", "gravity": "1 standard", "terrain": "desert", "surface_water": "1", "population": "200000", "residents": [ "https://swapi.co/api/people/1/", "https://swapi.co/api/people/2/", "https://swapi.co/api/people/4/", "https://swapi.co/api/people/6/", "https://swapi.co/api/people/7/", "https://swapi.co/api/people/8/", "https://swapi.co/api/people/9/", "https://swapi.co/api/people/11/", "https://swapi.co/api/people/43/", "https://swapi.co/api/people/62/" ], "films": [ "https://swapi.co/api/films/5/", "https://swapi.co/api/films/4/", "https://swapi.co/api/films/6/", "https://swapi.co/api/films/3/", "https://swapi.co/api/films/1/" ], "created": "2014-12-09T13:50:49.641000Z", "edited": "2014-12-21T20:48:04.175778Z", "url": "https://swapi.co/api/planets/1/" } { "name": "C-3PO", "height": "167", "mass": "75", "hair_color": "n/a", "skin_color": "gold", "eye_color": "yellow", "birth_year": "112BBY", "gender": "n/a", "homeworld": "https://swapi.co/api/planets/1/", "films": [ "https://swapi.co/api/films/2/", "https://swapi.co/api/films/5/", "https://swapi.co/api/films/4/", "https://swapi.co/api/films/6/", "https://swapi.co/api/films/3/", "https://swapi.co/api/films/1/" ], "species": [ "https://swapi.co/api/species/2/" ], "vehicles": [], "starships": [], "created": "2014-12-10T15:10:51.357000Z", "edited": "2014-12-20T21:17:50.309000Z", "url": "https://swapi.co/api/people/2/" } { "name": "Darth Vader", "height": "202", "mass": "136", "hair_color": "none", "skin_color": "white", "eye_color": "yellow", "birth_year": "41.9BBY", "gender": "male", "homeworld": "https://swapi.co/api/planets/1/", "films": [ "https://swapi.co/api/films/2/", "https://swapi.co/api/films/6/", "https://swapi.co/api/films/3/", "https://swapi.co/api/films/1/" ], "species": [ "https://swapi.co/api/species/1/" ], "vehicles": [], "starships": [ "https://swapi.co/api/starships/13/" ], "created": "2014-12-10T15:18:20.704000Z", "edited": "2014-12-20T21:17:50.313000Z", "url": "https://swapi.co/api/people/4/" } { "name": "Owen Lars", "height": "178", "mass": "120", "hair_color": "brown, grey", "skin_color": "light", "eye_color": "blue", "birth_year": "52BBY", "gender": "male", "homeworld": "https://swapi.co/api/planets/1/", "films": [ "https://swapi.co/api/films/5/", "https://swapi.co/api/films/6/", "https://swapi.co/api/films/1/" ], "species": [ "https://swapi.co/api/species/1/" ], "vehicles": [], "starships": [], "created": "2014-12-10T15:52:14.024000Z", "edited": "2014-12-20T21:17:50.317000Z", "url": "https://swapi.co/api/people/6/" } { "name": "Beru Whitesun lars", "height": "165", "mass": "75", "hair_color": "brown", "skin_color": "light", "eye_color": "blue", "birth_year": "47BBY", "gender": "female", "homeworld": "https://swapi.co/api/planets/1/", "films": [ "https://swapi.co/api/films/5/", "https://swapi.co/api/films/6/", "https://swapi.co/api/films/1/" ], "species": [ "https://swapi.co/api/species/1/" ], "vehicles": [], "starships": [], "created": "2014-12-10T15:53:41.121000Z", "edited": "2014-12-20T21:17:50.319000Z", "url": "https://swapi.co/api/people/7/" } { "name": "R5-D4", "height": "97", "mass": "32", "hair_color": "n/a", "skin_color": "white, red", "eye_color": "red", "birth_year": "unknown", "gender": "n/a", "homeworld": "https://swapi.co/api/planets/1/", "films": [ "https://swapi.co/api/films/1/" ], "species": [ "https://swapi.co/api/species/2/" ], "vehicles": [], "starships": [], "created": "2014-12-10T15:57:50.959000Z", "edited": "2014-12-20T21:17:50.321000Z", "url": "https://swapi.co/api/people/8/" } { "name": "Biggs Darklighter", "height": "183", "mass": "84", "hair_color": "black", "skin_color": "light", "eye_color": "brown", "birth_year": "24BBY", "gender": "male", "homeworld": "https://swapi.co/api/planets/1/", "films": [ "https://swapi.co/api/films/1/" ], "species": [ "https://swapi.co/api/species/1/" ], "vehicles": [], "starships": [ "https://swapi.co/api/starships/12/" ], "created": "2014-12-10T15:59:50.509000Z", "edited": "2014-12-20T21:17:50.323000Z", "url": "https://swapi.co/api/people/9/" } { "name": "Shmi Skywalker", "height": "163", "mass": "unknown", "hair_color": "black", "skin_color": "fair", "eye_color": "brown", "birth_year": "72BBY", "gender": "female", "homeworld": "https://swapi.co/api/planets/1/", "films": [ "https://swapi.co/api/films/5/", "https://swapi.co/api/films/4/" ], "species": [ "https://swapi.co/api/species/1/" ], "vehicles": [], "starships": [], "created": "2014-12-19T17:57:41.191000Z", "edited": "2014-12-20T21:17:50.401000Z", "url": "https://swapi.co/api/people/43/" } { "name": "Cliegg Lars", "height": "183", "mass": "unknown", "hair_color": "brown", "skin_color": "fair", "eye_color": "blue", "birth_year": "82BBY", "gender": "male", "homeworld": "https://swapi.co/api/planets/1/", "films": [ "https://swapi.co/api/films/5/" ], "species": [ "https://swapi.co/api/species/1/" ], "vehicles": [], "starships": [], "created": "2014-12-20T15:59:03.958000Z", "edited": "2014-12-20T21:17:50.451000Z", "url": "https://swapi.co/api/people/62/" } Overfetching
  13. 13. /people/1/ /planets/1/ /people/*/ x10 ... SELECT * FROM ... SELECT ... x10 ... SELECT * FROM ... Round trips
  14. 14. }); }); }); }); }); }); }); }); }); }); }); }); }); }); }); }); }); }); }); }); }); }); Boilerplate code
  15. 15. Solutions?
  16. 16. /person_profile/1/
  17. 17. Endpoints Explosion https://swapi.co/api/person_profile https://swapi.co/api/person_profile_v2 https://swapi.co/api/person_profile_android https://swapi.co/api/person_profile_ios
  18. 18. /person/1/?include=homeworld.residents &fields[person]=name,gender,height,weight &fields[planet]=name http://jsonapi.org
  19. 19. Structured Query Language Graph GraphQL
  20. 20. https://github.com/facebook/graphq GraphQL Working Draft – October 2016 Introduction This is a Draft RFC Specification for GraphQL, a query language created by Facebook in 2012 for describing the capabilities and requirements of data models for client‐server applications. The development of this standard started in 2015. GraphQL is a new and evolving language and is not complete. Significant enhancement will continue in future editions of this specification.
  21. 21. { "data": { "person": { "name": "C-3PO", "homeworld": { "name": "Tatooine", "residents": [ { "name": "Luke Skywalker", }, { "name": "C-3PO", }, ... ] } } } } Luke Skywalker Gender: Male | Height: 172cm | Mass: 77kg Homeworld: Tattoine Planetmates: C-3PO Darth Vader Owen Lars R5-D5 Beru Whitesun Iars Biggs Darklighter Shmi Skywlaker Cliegg Lars
  22. 22. /people/1/ /planets/1/ /people/*/ x10 ... SELECT * FROM ... SELECT ... x10 ... SELECT * FROM ...
  23. 23. http://swapi.apis.guru/ SELECT * FROM ... SELECT * FROM ... SELECT * FROM ... { person(personID: 1) { name … } } Before: 12 SQL queries After: 3 SQL query
  24. 24. How to call it? 1 const getPerson = swapiFetcher(` 2 query getPerson(id: ID!) { 3 person(personID: $id) { 4 name 5 } 6 } 7 `); 8 9 const result = await getPerson({id: 1}); 10 console.log(result.data); 11 // { person: { name: "Luke Skywalker" } }
  25. 25. 1 function swapiFetcher(query) { 2 return variables => fetch('http://swapi.apis.guru/', { 3 method: 'post', 4 headers: { 'Content-Type': 'application/json' }, 5 body: JSON.stringify({ 6 query, 7 variables 8 }), 9 }).then(response => response.json()); 10 } The most simple SDK
  26. 26. http://bit.ly/relay-vs-apollo ● Caching ● Integration with React, Angular, Vue, ... Relay Apollo
  27. 27. React Apollo HOC 1 function Profile({ data: { person } }) { 2 return ( 3 <div> /* ... */ </div> 4 ); 5 } 6 7 export default graphql(gql ` 8 query getPerson($id: ID) { 9 # ... 10 } 11 `)(Profile);
  28. 28. https://www.howtographql.com/
  29. 29. “GraphQL is unapologetically driven by the requirements of views and the front‐end engineers that write them.” – GraphQL specification
  30. 30. type Query { person(personID: ID!): Person } type Person { name: String homeworld: Planet } type Planet { name: String residents: [Person!] } Schema(SDL) { person(personID: 1) { name homeworld { name residents { name } } } } Query
  31. 31. Query result Luke Skywalker Tatooine ....Luke Skywalker Cliegg Lars homeworld residents
  32. 32. NO FORCE REQUIRED!
  33. 33. 1 import * as sqlite from 'sqlite'; 2 import * as express from 'express'; 3 import * as graphqlHTTP from 'express-graphql'; 4 import { buildSchema } from 'graphql'; Dependencies
  34. 34. 78 const db = await sqlite.open('./sw.sqlite3', {Promise}); 79 const app = express(); 80 app.use('/graphql', graphqlHTTP({ 81 schema: buildSchema(SW_SDL), 82 rootValue: new Query(), 83 context: { db }, 84 })); 85 app.listen(8888); GraphQL Server
  35. 35. class Query { person(args, context) { // ... } } class Person { homeworld(args, context) { // ... } } class Planet { residents(args, context) { // ... } } Resolvers type Query { person(personID: ID!): Person } type Person { name: String # ... homeworld: Planet } type Planet { name: String residents: [Person!] } Schema
  36. 36. Root value 28 class Query { 29 async person(args, context) { 30 const row = await context.db.get( 31 'SELECT * FROM person WHERE id = ?', 32 args.personID, 33 ); 34 if (!row) { 35 throw new Error(`Unknown personID`); 36 } 37 return new Person(row); 38 } 39 }
  37. 37. class Query { person(args, context) { // ... } } class Person { homeworld(args, context) { // ... } } class Planet { residents(args, context) { // ... } } SELECT * FROM person WHERE id = $arg.personID SELECT * FROM planets WHERE id = $this.planetID SELECT * FROM person WHERE homeworld = $this.ID
  38. 38. 94 https://github.com/IvanGoncharov/swapi-demohttps://github.com/IvanGoncharov/swapi-demo
  39. 39. ● Work with any data source (SQL, NoSQL, CMS, ...) ● Can join data from multiple sources ● Can be executed in parallel ● You can write them in any languages (if it has library) GraphQL Resolvers
  40. 40. type Person { name: String # ... numberOfVotes: String averageRating: Float } type Mutation { addStars(personID: ID!, numberOfStars: Int!): Person }
  41. 41. { "data": { "addStars": { "name": "Han Solo", "averageRating": 8.1, "numberOfVotes": 18204 } } } mutation { addStars( personID: 14 numberOfStars: 10 ) { name averageRating numberOfVotes } }
  42. 42. GraphQL is just a query language
  43. 43. Maturity Best practices => Partial Server libraries => Basic Cloud => AWS AppSync Client libraries => Apollo/Relay Tooling => Exiting
  44. 44. Why The Future is GraphQL
  45. 45. https://github.com/APIs-guru
  46. 46. Not covered today :( ● Type system features (Interfaces, Unions, …) ● Advance query features (Aliases, Fragments) ● Introspection (Reflection) ● Versioning - you don’t need it ● Subscriptions - Real time notifications (currently only WebSockets) https://graphql.org
  47. 47. Tomorrow 14:05 - 15:00
  48. 48. Questions? http://bit.ly/js-fest-graphql

×