All Articles

GraphQL Explained

As I’m learning GraphQL recently, it’s necessary to jot something down about how I go through the concepts and make sure no confusion happens, albeit with no real-world experience for now.

Some concepts

GraphQL is a query language for your APIs. It’s also a runtime for fulfilling queries with your data. The GraphQLservice is transport agnostic but is typically served over HTTP. GraphQL playground

The QL specifies to Query Language, but GraphQL and SQL are completely different.SQL is a query language for databases. GraphQL is a query language for the internet.

Design principles of GraphQL:

  • Hierarchical: A GraphQL query is hierarchical. Fields are nested within other fields and the query is shaped like the data that it returns.
  • Product-centric: GraphQL is driven by the data needs of the client and the language and runtime that support the client.
  • Strong typing: A GraphQL server is backed by the GraphQL type system. In the schema, each data point has a specific type against which it will be validated.
  • Client-specified queries: A GraphQL server provides the capabilities that the clients are allowed to consume.
  • Introspective: The GraphQL language is able to query the GraphQL server’s type system.

GraphQL Versus REST: link

What’s the drawback of REST?

  • Overfetching, avoid extra fields being fetched
  • Underfetching, avoid additional requests. The GraphQL solution to underfetching is to define a nested query and then request the data all in one fetch
  • Lack of flexibility. With GraphQL, the typical architecture involves a single endpoint. The single endpoint can act as a gateway and orchestrate several data sources, but the one endpoint still makes the organization of data easier.

    In this discussion of REST drawbacks, it’s important to note that many organizations use GraphQL and REST together. Setting up a GraphQL endpoint that fetches data from REST endpoints is a perfectly valid way to use GraphQL. It can be a great way to incrementally adopt GraphQL at your organization.

This is how REST requests look like: REST requests And this is how GraphQL requests look like: GraphQL requests

Apollo graphql is a platform implementation of GraphQL designed for building modern data-driven applications.

GraphQL Query Language

Types: query, mutation, subscription

Cheatsheet

To check the GraphQL Schema Language, we can use the cheatsheet. cheatsheet

About GraphQL queries syntax, we can use devhints cheatsheet.

Queries: reading data

In the GraphQL query language, fields can be either scalar types or object types.

  • the five built-in scalar types: integers (Int), floats (Float), strings (String), Booleans (Boolean), and unique identifiers (ID)
  • GraphQL object types are groups of one or more fields that you define in your schema.

A GraphQL query document can contain definitions for operations and fragments. Fragments are selection sets that can be reused in multiple operations.

In each case so far, we’ve returned lists of a single type. If you wanted a list to return more than one type, you could create a union type, which creates an association between two different object types.

Mutations: writing/updating data

Mutations are defined similarly as queries. They have names. They can have selection sets that return object types or scalars. The difference is that mutations perform some sort of a data change that affects the state of your backend data.

Variables replace the static value in the query so that we can pass dynamic values, instead.

mutation createSong($title:String! $numberOne:Int $by:String!) {
  addSong(title:$title, numberOne:$numberOne, performerName:$by) {
    id
    title
    numberOne
  }
}
Subscriptions: real time update

Facebook live ‘Likes’ are a real-time use case that is powered by subscriptions. Every client is subscribed to the like event and sees likes being updated in real time. We listen to changes over a WebSocket.

To stop listening for status changes, you need to unsubscribe from your subscription.

Introspection

Introspection is the ability to query details about the current API’s schema. When getting to know a new GraphQL API, it is a good idea to find out what fields are available on the root types.

query roots {
  __schema {
    queryType {
      ...typeFields
    }
    mutationType {
      ...typeFields
    }
    subscriptionType {
      ...typeFields
    }
  }
}

fragment typeFields on __Type {
  name
  fields {
    name
  }
}

GraphQL Schema Definition Language (SDL)

In GraphQL, a type represents a custom object and these objects describe your application’s core features.

A schema is a collection of type definitions. You can write your schemas in a JavaScript file as a string or in any text file. These files usually carry the .graphql extension.

At the heart of all GraphQL projects is a solid, well-defined schema. This serves as a roadmap and a contract between the frontend and backend teams to ensure that the product built always serves the schema.

Some concepts in GraphQL Schema:

  • Scalar types, built in/custom scalar types, graphql-custom-types
  • Enums
  • Connections and Lists. Most list definitions are non-nullable lists of non-nullable values.

    • One to one
    • One to many
    • Many to many
    • Through type
  • Union type example
  • Interface exampleIn general, if the objects contain completely different fields, it is a good idea to use union types. They are very effective. If an object type must contain specific fields in order to interface with another type of object, you will need to use an interface rather than a union type.
  • Arguments with type definition, could be used for:

    • querying or filtering
    • data paging
    • sorting, sort-by and sort-order, usually enum type
  • Schema about ‘Mutations’. Mutations should represent the verbs in your application. They should consist of the things that users should be able to do with your service. When designing your GraphQL service, make a list of all of the actions that a user can take with your application. Those are most likely your mutations.
  • Mutation variables, similar to query variables.
  • Input type. There is a better way to organize these arguments using input types. An input type is similar to the GraphQL object type except it is used only for input arguments.
  • Return type
  • Subscription types, Subscription types are no different than any other object type in the GraphQL schema definition language.

Some notes about real world implementations

Resolvers

Check code example

A schema describes the data requirements but doesn’t perform the work of getting that data. That work is handled by resolvers.

A resolver is a function that returns data for a particular field. Resolver functions return data in the type and shape specified by the schema. Resolvers can be asynchronous and can fetch or update data from a REST API, database, or any other service.

Resolvers are key to the implementation of GraphQL. Every field must have a corresponding resolver function. The resolver must follow the rules of the schema. It must have the same name as the field that was defined in the schema, and it must return the datatype defined by the schema.

When we define a GraphQL schema, we describe the data requirements of our application. With resolvers, we can powerfully and flexibly fulfill those requirements. Functions give us this power and flexibility. Functions can be asynchronous, can return scalar types and return objects, and can return data from various sources. Resolvers are just functions, and every field in our GraphQL schema can map to a resolver.

Subscriptions

In addition to fetching data using queries and modifying data using mutations, the GraphQL spec supports a third operation type, called subscription.

Please refer to Apollo docs about subscriptions.

Security

  1. Timeout: A request timeout is a first defense against large or malicious queries. A request timeout allows only a certain amount of time to process each request.
  2. Data Limitations: You can return a specific number of records, or a page of data, by allowing your queries to specify how many records to return.
  3. Limiting Query Depth
  4. Limiting Query Complexity
  5. Monitor service, like Apollo Engine

Schema first development

Problems with web projects usually stem from a lack of communication or miscommunication about what should be built. Schemas provide clarity and communication, which is why many projects practice schema-first development.

Reference:

  1. Learning GraphQL, by Alex Banks, Eve Porcello
  2. https://www.howtographql.com/
  3. Real world example from the book: Chapter 5 (GraphQL Server), [Chapter 6]