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

From learning to thinking in GraphQL

Glenn Reyes
December 05, 2018

From learning to thinking in GraphQL

GraphQL has been unlocking tons of possibilities in the JavaScript world. Over the past years, we've witnessed a lot of improvements in the spec, a huge amount of toolings and whole new ecosystem around GraphQL.

Things are evolving really fast in the web and we are forced to keep learning and building products at this pace. Being new to GraphQL, a lot concerns and hurdles need to be overcome such as Authorization & Authentication, Storing Data, Caching, Project Structure & Organization, Real-time Events and many more.

In this talk I will share my journey from learning GraphQL, over building GraphQL apps and solving above challenges to thinking in GraphQL.

Glenn Reyes

December 05, 2018
Tweet

More Decks by Glenn Reyes

Other Decks in Programming

Transcript

  1. – graphql.org “GraphQL is a query language for APIs and

    a runtime for fulfilling those queries with your existing data.” What's GraphQL?
  2. { me { name age bio twitter } } {

    "me" { "name": "Glenn", "age": 31, "bio": "Engineer", "twitter": "@glnnrys" } } Ask for what you need get exactly that
  3. apollo-server const typeDefs = gql` type User { id: ID!

    name: String } type Query { me: User } `; const resolvers = { Query: { me: (obj, args, context) => getUserById(context.user.id), }, }; const server = new ApolloServer({ typeDefs, resolvers }); server.listen().then(({ url }) => { console.log(` Server ready at ${url}`); });
  4. ⚡ Zero-config GraphQL server ⚡ Run server by single command

    ⚡ Uses Apollo-Server under the hood ⚡ TypeScript support ⚡ Live-Reload ⚡ ES features ⚡ Friendly Errors ⚡ Hides all the boilerplate Graphpack
  5. # src/schema.graphql type User { coverPhoto: String! profilePhoto: String! displayName:

    String id: ID! username: ID! bio: String posts: [String!]! }
  6. # src/schema.graphql type User { coverPhoto: String! profilePhoto: String! displayName:

    String id: ID! username: ID! bio: String posts: [String!]! }
  7. # src/schema.graphql type User { coverPhoto: String! profilePhoto: String! displayName:

    String id: ID! username: ID! bio: String posts: [String!]! } posts: [String!]!
  8. type Post { id: ID! createdAt: DateTime! message: String! }

    type User { coverPhoto: String! profilePhoto: String! displayName: String id: ID! username: ID! bio: String posts: [Post!]! } # src/schema.graphql
  9. type Post { id: ID! createdAt: DateTime! message: String! }

    type User { coverPhoto: String! profilePhoto: String! displayName: String id: ID! username: ID! bio: String post: [Post!]! } # src/schema.graphql coverPhoto: String! profilePhoto: String!
  10. type Photo { createdAt: String! filename: String! title: String url:

    String! updatedAt: DateTime! } type Post { id: ID! createdAt: DateTime! message: String! } type User { coverPhoto: Photo! profilePhoto: Photo! displayName: String id: ID! username: ID! bio: String post [Post!]! }
  11. # src/schema.graphql const resolvers = { Query: { user: (obj,

    args) => getUser(args.id), }, User: { posts: (obj, args) => getPostsByUser(args.id), }, };
  12. { "user": { "profilePhotoId": "15942", "coverPhotoId": "159425", "displayName": "Glenn Reyes",

    "userName": "glnnrys", } } /api/user/glnnrys /api/photo/159425 { "photo": { "id": "159425", "url": "https://myimgcdn.com/159425.jpg", "taggedUsers": ["thekitze", "mmatuzo"] } } /api/user/thekitze { "user": { "profilePhotoId": "15934", "coverPhotoId": "159655", "displayName": "Kitze", "userName": "thekitze", } }
  13. import gql from 'graphql-tag'; import { Query } from 'react-apollo';

    const ProfilePage = props => ( <Query query={gql` query getProfile($username: ID!) { profile(username: $username) { profilePhoto displayName username bio } } `} variables={{ username: props.username }} > {({ data, loading }) => { if (loading) return 'Loading ...'; if (!data) return null; return <Profile data={data.profile} />; }} </Query> );
  14. query getProfile { profile(username: "glnnrys") { coverPhoto profilePhoto displayName username

    bio } } query getPosts { profile(username: "glnnrys") { posts { date id message } } }
  15. only available in the alpha preview of Apollo! query getProfile

    { profile(username: "glnnrys") { coverPhoto profilePhoto displayName username bio posts @defer { date id message } } }
  16. # src/schema.graphql type Mutation { changeProfilePhoto( input: ChangeProfilePhotoInput! ): ChangeProfilePhotoPayload!

    } input ChangeProfilePhotoInput { user: User! file: File! } type ChangeProfilePhotoPayload { clientMutationId: ID! photo: Photo! }
  17. ⭐ Naming – Verb + Object (eg. updateBio, submitPost) ⭐

    Specificity – Make mutations as specific as possible ⭐ Input object – Single, unique & required ⭐ Unique Payload type – Like ChangeProfilePhotoPayload ⭐ Nesting is fine! https://blog.apollographql.com/designing-graphql-mutations-e09de826ed97
  18. // src/context.js const context = (req) => { const isLoggedIn

    = req.user ? true : false; return { isLoggedIn, user, }; }; export default context; Context
  19. // src/context.js const context = { users: new DataLoader(keys =>

    fetch(`/api/users/?ids=${keys.join(',')}`)), } // src/resolvers.js const resolvers { Query: { user: (obj, args, context) => context.users.load(args.id), }, };
  20. knex.js const knex = require('knex')({ client: 'mysql', version: '8.0', connection:

    { host : '127.0.0.1', user : 'your_database_user', password : 'your_database_password', database : 'myapp_test' } }); knex .select(['id', 'name', 'bio']) .from('people') .where({ gender: 'female' })
  21. src !"" models % !"" createSpeaker.js % !"" createTalk.js %

    !"" deleteSpeaker.js % !"" getSpeakerById.js % !"" getSpeakers.js % !"" getTalkById.js % #"" getTalks.js !"" resolvers % !"" Mutation.js % !"" Query.js % !"" Speaker.js % !"" Talk.js % #"" index.js #"" types !"" Mutation.graphql !"" Query.graphql !"" Speaker.graphql !"" Talk.graphql #"" schema.graphql By types
  22. src !"" Mutation % !"" resolver.js % #"" type.graphql !""

    Query % !"" helpers.js % !"" models.js % !"" resolver.js % #"" type.graphql !"" Speaker % !"" resolver.js % #"" type.graphql #"" Talk !"" resolver.js #"" type.graphql By feature
  23. Always start simple Switch gruadually depending on your use case

    Dont worry much about folder structure!!
  24. ⚡ GraphQL core concepts ⚡ Graphpack – Building zero-config GraphQL

    servers ⚡ Approach to write – Mental Model, Types, Resolvers, Defer ⚡ Mutations – Naming, Specifity, Unique Input & Payload type ⚡ Authentication & access control ⚡ Data storage – GraphQL not tied to any database ⚡ Batch and cache with Dataloader ⚡ Avoid bikeshedding on folder structure