Overview

In this series we’re going to build a GraphQL backend for a forum in Elixir and TypeScript, and clients for it in each of Vue, React Native, Elm, and Flutter. Before we get into the details, let’s start by explaining what GraphQL is,

GraphQL is a query language for strongly typed APIs. It is a declarative language used to fetch data with queries, make changes to it with mutations, and learn about data that’s changing in real-time with subscriptions..

That’s a boring description though. A more succinct and exciting way to say the same thing is: with GraphQL, you just describe the data you want, and you get it.

What does it mean for an API to be strongly typed? It means that a given field returns an explicitly-specified type of data, and a GraphQL server is incapable of returning data that doesn’t match the specification. Any attempt to do so results in an error.

With GraphQL, when you’re building a client, you can be guaranteed either to receive an error, or to receive data that matches the specification. This helps you write clients with confidence. Additionally, GraphQL APIs expose their specification - or schema - and tools can use it to present detailed interactive documentation or generate client code.

We can look at the schema of what we’re going to build using GraphQL Playground.

We can query for categories:

query {
  categories {
    entries {
      id
      title
    }
  }
}

The server will take this query and return the data we requested in the described shape. The server fulfills the request however it chooses.

Frequently this means interacting with a database, but there are many other use cases. As an example, Gatsby implements a GraphQL interface to the filesystem to help you organize data when building static sites. Sometimes people use GraphQL to aggregate disparate REST APIs. GraphQL is just a protocol - go crazy.

As a protocol, GraphQL is not tied to any particular programming language. We’ve built software using GraphQL with Ruby, Elixir, JavaScript, Elm, Dart, and Python. Whatever your preferred programming language is, you’ll inevitably find that there is a robust GraphQL implementation.

In this course, we will build a GraphQL server with both JavaScript and Elixir. The JavaScript backend takes advantage of the Apollo Server library, while the Elixir backend uses Absinthe.

Additionally, we will build client applications in each of Vue, Flutter, Elm, and React Native. In each case, GraphQL helps make the code clearer. Building clients for a GraphQL server is especially pleasant. Aside from the basic guarantees that strong typing provides, you can take advantage of code generators to automatically build type annotations or complete client libraries with type safety baked in.

REST versus GraphQL

REST

Imagine you have an existing back-end implementing your business logic, and you want to build a mobile app that consumes the API. Historically, this has meant determining how to use the existing API endpoints to collect all of the data to present to the user. Depending on how well the client interface matches the API semantics, this could require multiple API calls.

Imagine you need a post’s user’s avatar and the backend developer didn’t anticipate this use case. You’re left with two options:

Request changes to the API endpoint in question. Wait for someone to make the requested changes. If the new data is added to an existing endpoint, then clients that don’t make use of it will waste time downloading useless data. If a new endpoint was added, the maintenance burden on the backend is increased. Construct the data that you needed using multiple requests. This might help the client development move faster, but now you introduced an N+1 query onto the client. That’s not going to end well.

This is the API-first way of viewing things.

GraphQL

With GraphQL, you can take a more product-centric approach. The client can produce a single query that declares the data a screen needs, and get it all at once. If you need a post’s user’s avatar, you simply declare that you need it in the query.

GraphQL’s strong typing allows you to compose the data that you need, when you need it.

The language

GraphQL is a query language for interacting with GraphQL services.

A GraphQL document can contain queries, mutations, and subscriptions.

Queries

Queries are used to request data. For example, our schema might contain the following:

type Query {
  thread(id: ID!): Thread
}

We can send a document to the server to execute this query:

query {
  thread(id: “someid”) {
    id
    title
    posts {
      id
      body
    }
  }
}

This document requests a thread by id. If there’s a thread with that id, it will return that thread’s id and title fields, as well as a posts field that includes a list of posts. The posts will each have an id field and a body field. To recap: a query is a declarative way to request precisely the data you want from the server.

It's worth noting that the client is in complete control of the data requested from the GraphQL server. The client could easily request more information from a post, for example, by just modifying the document. We can query anything we think is important for our client or for a given screen we are working on. This is why we say GraphQL is product-centric. We simply declare what we need, and the server provides it.

Mutations

To write data to the server, you send a Mutation.

Let's imagine we want to create a Thread. In this example, to create a thread we just need a title.

Assume our server provides a createThread mutation that takes a single argument named title, which is a required field and must be a String, and returns a Thread that is guaranteed not to be null in the event of success. Let’s see what that looks like in the schema:

type Mutation {
  createThread(title: String!): Thread!
}

We can construct a document that runs this mutation:

mutation {
  createThread(title: “Josh”) {
    id
    title
  }
}

Here we’re requesting the id and title fields from the Thread type that this mutation returns.

Subscriptions

Subscriptions are long-lived requests that return data in response to some event.

Let's say in our Forum, we want to be notified when a new category is created. The schema might contain the following:

type Subscription {
  categoryAdded: Category
}

We could send a document to the server asking to subscribe to this event:

subscription {
  categoryAdded {
    id
    title
  }
}

As long as that subscription is running, each time a new category is added we’ll be notified of its id and title.

Solving problems?

If you didn't notice what GraphQL is good at yet, here’s a summary:

  • Using GraphQL we don't need to make multiple round trips to fetch data for a view.
  • Requests are composable, which means we can easily add or remove fields according to our view.
  • The schema describes every operation and every data type used in the system. Strongly typed APIs ftw.
  • Extremely good documentation is automatically generated based on the schema.
  • Clients can use the schema for code-generation to create clients.

Neat, but is anyone using it?

A huge list of companies are using GraphQL in production. The New York Times have been using GraphQL for over a year. Coursera is also using it with microservices. We at Smooth Terminal are using GraphQL for everything, including static pages, with absinthe-phoenix.

Here’s a short and incomplete list of companies using it today..

  • SmoothTerminal :)
  • Facebook
  • GitHub
  • Pinterest
  • Intuit
  • Shopify
  • Atlassian
  • PayPal
  • ProductHunt
  • Twitter
  • Yelp
  • Coursera

Summary

In summary, GraphQL is great and you should be using it. If you’re interested but don’t really know where to start, stick around. This course will walk you through GraphQL from both the backend and frontend perspectives!

Resources

login to comment
  1. Comments for Introduction to GraphQL