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

Building tools for GraphQL

Building tools for GraphQL

Adopting GraphQL can be fairly demanding and it takes some time to find the right tooling. What can we do to improve DX and supercharge our GraphQL development? Let's deep-dive into GraphQL tooling that help us building GraphQL at scale.

Glenn Reyes

October 11, 2018
Tweet

More Decks by Glenn Reyes

Other Decks in Programming

Transcript

  1. server.js > node server.js const { ApolloServer, gql } =

    require('apollo-server'); // The GraphQL schema const typeDefs = gql` type Query { "A simple type for getting started!" hello: String } `; // A map of functions which return data for the schema. const resolvers = { Query: { hello: () => 'world', }, }; const server = new ApolloServer({ typeDefs, resolvers, }); server.listen().then(({ url }) => { console.log(` Server ready at ${url}`); });
  2. > yarn add graphpack 
 > yarn dev
 > yarn

    build package.json "scripts": { "dev": "graphpack", "build": "graphpack build" }
  3. #!/usr/bin/env node const nodemon = require('nodemon'); const path = require('path');

    const { once } = require('ramda'); const webpack = require('webpack'); const paths = require('../config/paths'); const webpackConfig = require('../config/webpack.config'); const compiler = webpack(webpackConfig); const serverPaths = Object.keys(compiler.options.entry).map(entry => path.join(compiler.options.output.path, `${entry}.js`), ); compiler.watch( webpackConfig.watchOptions, once(error => { if (error) return; nodemon({ script: serverPaths[0], watch: serverPaths }).on( 'quit', process.exit, ); }), ); ./bin/graphpack
  4. const typeDefs = gql` type Author { id: Int name:

    String posts: [Posts!]! } type Post { id: Int title: String comments: [Comment!]! } type Query { mainAuthor: Author } `; const resolvers = { Query: { mainAuthor: () => ({ id: 1 name: 'Glenn', posts: [{ id: 1, title: 'Hello World' }], }), }, Author: { posts: async (parent) => { const comments = await fetchPostCommentsFromAuthor(parent.id); return { ...parent.posts, comments }; } }, };
  5. { mainAuthor { id name posts { id title }

    } } Comments are still fetched by the `posts` resolver Query const resolvers = { Query: { mainAuthor: () => ({ id: 1 name: 'Glenn', posts: [{ id: 1, title: 'Hello World' }], }), }, Author: { posts: async (parent) => { const comments = await fetchPostCommentsFromAuthor(parent.id); return { ...parent.posts, comments }; } }, };
  6. –Apollo Docs “This argument should only be used in advanced

    cases, but it contains information about the execution state of the query, including the field name, path to the field from the root, and more. It’s only documented in the GraphQL.js source code” `info`
  7. const resolver = { Author: { posts: parent => getPostsbyAuthor(parent.id),

    }, }; API … into const resolver = { Author: { posts: resolveable(parent => getPostsbyAuthor(parent.id)), }, };
  8. const resolvable = (resolver) => (parent, args, context, info) =>

    { // TODO return resolver(parent, args, context, info) };
  9. const GET_DOGS = gql` query GetDogs { dogs { id

    name } } `; const GoodDogsBrent = () => ( <Query query={GET_DOGS}> {({ loading, error, data }) => { if (error) return <Error /> if (loading || !data) return <Fetching /> return <DogList dogs={data.dogs} /> }} </Query> )
  10. const GET_DOGS = gql` query GetDogs { dogs { id

    name } } `; const GoodDogsBrent = () => ( <Query query={GET_DOGS}> {({ loading, error, data }) => { if (error) return <Error /> if (loading || !data) return <Fetching /> return <DogList dogs={data.dogs} /> }} </Query> ) What if … const GetDogsQuery = gql` query GetDogs { dogs { id name } } `; const GoodDogsBrent = () => ( <GetDogsQuery> {({ loading, error, data }) => { if (error) return <Error /> if (loading || !data) return <Fetching /> return <DogList dogs={data.dogs} /> }} </GetDogsQuery> )
  11. and even … const GetDogsQuery = gql` query GetDogs {

    dogs { id name } } `; const GoodDogsBrent = () => ( <GetDogsQuery> {({ loading, error, data }) => { if (error) return <Error /> if (loading || !data) return <Fetching /> return <DogList dogs={data.dogs} /> }} </GetDogsQuery> ) import GetDogsQuery from './dogsQuery.graphql' const GoodDogsBrent = () => ( <GetDogsQuery> {({ loading, error, data }) => { if (error) return <Error /> if (loading || !data) return <Fetching /> return <DogList dogs={data.dogs} /> }} </GetDogsQuery> )