GraphQL + Apollo – Part 1: An Introduction

This past September, I attended the Strange Loop conference in St. Louis. Among the plethora of great talks that I attended was one about GraphQL, given by Lee Byron. This talk, supplemented by a great deal of research, convinced me that I should use GraphQL in the project that I started a couple of months ago.

This post is the first in a series of three that will cover Apollo and GraphQL. First, I will introduce the concept of GraphQL through the lens of Apollo, a set of JavaScript libraries and tools which allow for simple and extensible GraphQL clients and servers. Part 2 will take a deeper dive into a GraphQL server example, and Part 3 will open the doors to Apollo’s GraphQL client libraries.

What is GraphQL?

GraphQL is a data query language, a specification that defines a communication protocol between a client and server. It was developed in 2012 by Facebook for internal use, and in 2015, it was open-sourced by releasing a reference implementation and a public specification. At its core, GraphQL enables flexible, client-driven application development in a strongly typed environment.

Although the reference implementation is written in JavaScript (as is the code you’ll see in this post), GraphQL does not impose any language requirements. It also does not require any particular storage mechanism. Any GraphQL client can communicate with any matching GraphQL server to retrieve/mutate data on any data source. Simply put, GraphQL is an extremely powerful and productive environment for building robust web applications.

How Does It Work?

GraphQL clients communicate with GraphQL servers via queries and mutations. Queries and mutations are mechanisms for querying/mutating specific, well-defined data on a server.

The server defines a schema which defines the objects that can be queried, along with the types of data that correspond to the objects. A query also defines the shape of the resulting data, allowing the client to explicitly control the shape of the data being consumed.

For example, the schema below defines a Person object type with some fields:

type Person {
  name: String!
  age: Int
  gender: Gender
  height(unit: HeightUnit = METER) : Float
}

enum Gender {
  MALE
  FEMALE
}

type Query {
  personWithName(name: String!): Person
  guys: [Person]
  girls: [Person]
}

schema {
  query: Query
}

This schema also defines a few queries: PersonWithName, Guys, and Girls. PersonWithName takes a string argument and returns a single Person object. This Person object will contain a mandatory name field (the ‘!’ designates a mandatory field), and an optional age, gender, and height. This example also demonstrates the use of enum types and field arguments (e.g. the height field takes a unit as an argument).

Given this schema, a GraphQL client can send queries and specify the return fields. For example, a query like this:

{
  personWithName(name: "Joe") {
    name
    height(unit: FOOT)
  }
}

might yield a response like this:

{
  "data": {
    "personWithName": {
      "name": "Joe",
      "height": 5.92
    }
  }
}

This site is an excellent resource to dive into GraphQL, and I would sincerely recommend checking it out!

Introducing Apollo

Since GraphQL is simply a communication protocol between a client and server, there is a lot of opportunity for third-party support in various languages. As you might guess, there are various readily available solutions for client and server implementations.

For example, the the de-facto solution in Node with Express is express-graphql, of which Lee Byron is a major contributor. Then there are various client implementations, with one of the most popular being Facebook’s Relay.

However, Apollo is a Node package that I have been really excited about lately. Apollo provides both server and client libraries and is completely production-ready. The server offers extensions and tooling around Facebook’s GraphQL.js reference implementation, and it adds support for query batching, subscriptions, and more.

Apollo also has several customized client integrations such as React, Angular, iOS, and Android, along with a “Vanilla JS” implementation for use in any JavaScript environment.

My next post will dive into Apollo Server, including schema building, query resolution, and testing, so stay tuned!