GraphQL Tutorial — Getting Started

As originally posted at Jobstart.

Introduction

GraphQL is one of the most exciting technologies gaining developer attention in 2017. A viable alternative to RESTful APIs, GraphQL APIs provide a much more succinct and expressive way to read and write relational data between client and server.

Two of the more exciting pieces of technology within the GraphQL ecosystem are and , built by the folks at Apollo. In this post, we will focus on discussing high-level GraphQL concepts and getting a basic server up and running with .

You can get the finished source code here

Architecture

At a high level, GraphQL can be thought of as specification for creating strongly-typed transport-agnostic APIs. Before we dive into the nitty-gritty of our server, let’s take a quick moment to cover some basic GraphQL nomenclature:

  • A Query is a read-only operation made against a GraphQL server.
  • A Mutation is a read-write operation made against a GraphQL server.
  • A Resolver provides a mapping between a portion of a GraphQL operation and actual backend code responsible for handling it (similar to a controller in a RESTful MVC backend).
  • A Schema defines what queries and mutations can be performed against a GraphQL server, what each query or mutation takes as input, and what each query or mutation returns as output.
  • A Type defines the shape of output / response data that can be returned from the GraphQL server, including fields that are edges to other Types.
  • An Input is like a Type, but defines the shape of input data that is sent to a GraphQL server.
  • A Scalar is a primitive Type, such as a , , , , etc.

GraphQL’s domain of concern begins at the Client where the request is assembled, and ends at the Resolvers where the request is translated into actual backend code written in a language and paradigm of your choosing. GraphQL cares nothing about how you store your data or how your frontend works. It is simply a paradigm and language for making requests and rendering responses. With GraphQL, you can think of your internal data sources as a graph of relational data and traverse those relationships with a natural and expressive language.

First steps

Let’s spin up a basic “hello world” server so that we can get our hands dirty with an actual implementation.

If you don’t already have NodeJS configured on your system, you will need to install it.

We will be using esnext-node-starterkit as a project boilerplate, so let’s go ahead and clone that now:

Now, let’s quickly review our project structure:

  • will be the entry point of our server
  • will be where our Resolvers live
  • will be where our Schema lives

Our boilerplate comes with . Let's go ahead and create the other two files:

Schema

The top-level of a GraphQL Schema is always defined the same way, with a declaration, so let's write that at the top of our file:

The schema declaration will define a field. In the declaration above, we are mapping to an additional Type called , which will tell GraphQL what root fields our server can return, what their resolvers will take as input, and the type of the field. Let's define a field on our initial Query type:

Notice that, like in our schema definition, we are mapping to a separate Type, in the case . is a pre-defined Scalar Type in GraphQL, so we don't need to define it ourselves. The exclamation mark at the end of denotes that our field will always be a String, and never .

Finally, let’s export our GraphQL definitions:

Now that we have defined our Schema, let’s move on to our Resolvers.

Resolvers

“Resolvers” is a bit of a misnomer here. Because we only have a single field of Type , we only need a single Resolver to tell GraphQL how to fetch . Let's go ahead and write the Resolver now:

And that’s it! We don’t need to write any more code for our resolver to work. As an aside, it is worth noting that in NodeJS we can return a Promise from any Resolver if we need to do async work to fetch data. GraphQL will yield to the Promise and pass through whatever it resolves to, or throw an error for whatever it rejects as. In real world apps, we will usually call a model method from our resolver which returns a Promise that resolves to a shape that matches the Type returned by the Resolver (more on that in the next post).

Let’s bring it all together with Express and a bit of Express middleware and take our new GraphQL server for a spin!

To Hello World…

As stated before, GraphQL is simply a language for reading and writing data to and from a server. There are a variety of server-side implementations for NodeJS, Golang, Elixir, Ruby, Python, Java, and more. Because we are working with NodeJS in this tutorial, we will be using the popular NodeJS implementation graphql-server written by the folks at Apollo and maintained by their open source community.

To begin with, let’s install a few necessary packages to wire everything together:

Now let’s write our file and get our server up and running for a test:

Awesome! Let’s load up the server:

Our query will look like this:

Let’s test it out on a second terminal tab:

You should see output!

And beyond…

This is a rather simple demonstration. In a real world GraphQL backend, you will have Types that reference one another. Let’s make a quick modification to our server to see how that can work. Let’s create a new type that references a new type, rename the query to , and return the type from our query:

First, in our file, let's add the new Types and the relationship:

Next, we need to define a couple of extra resolvers in :

Let’s also add a better tool to test our GraphQL server with a simple change to :

Let’s test it again with our new structure and our new tool. Goto http://localhost:8080/graphiql.

Our query will look like this:

Now enter the above query, and click the run button, and Voilà!

Nice! We are now fetching relational data! has a relation with through the field. contains field of type . With GraphQL, we can traverse relational data in a declarative way. Remember, our Resolvers can return Promises, so we can go to our database and load data rather than simply returning fixture data as we are doing in our example.

In conclusion

We built a simple Hello World backend, but this is only scratching the surface with what we can do with GraphQL APIs. In the next post we will build a fully featured full-stack message feed app with an isomorphic React frontend and a GraphQL backend using Postgres as our data store, Redis for caching, and Elasticsearch for searching messages. We will cover fundamental concepts such as caching, access control, and error handling. Check back soon for a link!

Founder & CEO @BoltSourceIO