I’ve been hearing about GraphQL for months now, but for the longest time I really didn’t understand what it was.

Is it a new query language? A new type of database? Some other JavaScript black magic? Nope, none of the above.

GraphQL is a new API standard that provides a more efficient, powerful and flexible alternative to REST.

How to GraphQL

It’s an alternative to REST, so what? Why should I use GraphQL instead of REST endpoints?

Traditional REST endpoints return fixed data structures, usually with extra info clients don’t need, and require multiple endpoints (and HTTP calls) to get back all the necessary information. GraphQL does not.

**** Here's an example of two traditional HTTP calls to find students and their classes ****Call 1: HTTP get to: 'students/<id>'
Returns:
{ "student":
{
"id": 1,
"firstName":"Jane",
"lastName":"Smith"
}
}
Call 2: HTTP get to: 'students/<id>/classes'
Returns:
{ "classes":
[{
"id": 1,
"className":"math"
},
{
"id": 1,
"className":"english"
}]
}
**** Here is the same information as one GraphQL query ****
Query:
query { Student( id:1 ){
firstName
lastName
classes {
className
}
}
}
Returns:{ "data":
{ "Student":
{ "firstName":"Jane",
"lastName":"Smith",
"classes":
[{
"className": "math"
},
{
"className":"english"
}]
}
}
}

One thing that cannot be stressed enough is that GraphQL is not a query language for databases. GraphQL is a query language for APIs.

This makes it database agnostic, and makes it possible to be used in any context where an API is used.

And no, contrary to the fact that whenever GraphQL is mentioned, it seems to be in tandem with React (since Facebook invented both), GraphQL can be used everywhere a client communicates with an API (there’s server libraries for C, Go, Erlang, Java and more).

JavaScript is by far the most popular language to utilize with GraphQL, and it has some really excellent server packages that work in conjunction to make GraphQL easily implementable with projects. It can be run straight from the command line with Node.js when Graphql.js is installed, but it really shines when it’s integrated into a project with the GraphQL API server sitting as a layer between the client frontend and the server backend and database(s).

The implementation I’ve used is Apollo, and it integrates easily with various Node.js HTTP frameworks like Express, Connect, KOA, Hapi, etc. But that’s for another post.

Ok, you’ve piqued my interest. So how does GraphQL work?

Schemas: How GraphQL Defines and Structures the Data it Receives

**** Simple Schema Example for a Type Called Student ****type Student { 
firstName: String! #the exclamation mark means it's required
lastName: String!
}

The Schema Definition Language (SDL) is the syntax for writing schemas, and queries and mutations are composed to get back the required information from the server. Since the structure of the data returned from the single GraphQL endpoint is completely flexible, the query has to be extremely specific in what it requires.

If something is specified in the schema but not returned, the response will contain a null for that field, but it will not throw an exception as it sometimes happens with REST endpoints. However, if a specific field is not specified but is needed, the client won’t receive it until the schema is updated to include that field.

Queries: How GraphQL Asks for Data

**** Basic Query Asking the Server for All Students ****{ allStudents 
{
firstName
lastName
}
}
Returns: {"allStudents":
[{
"firstName":"Jane",
"lastName":"Smith"
},
{
"firstName":"John",
"lastName":"Doe"
}]
}

Mutations: How GraphQL Manipulates Data

  • create new data
  • update existing data
  • delete existing data
**** A Create Mutation to Make a New Student ****mutation { createStudent(firstName: "Robert", lastName: "Johnson") 
{
firstName
lastName
}
}
The server response would look like this:"createStudent": {
"firstName":"Robert",
"lastName":"Johnson"
}

Between queries to read data and mutations to manipulate data, all the CRUD functionality supplied by traditional REST endpoints is handled by GraphQL.

Regardless of the way you’re implementing the GraphQL server (connected to a single database, over a number of third party legacy systems or as a hybrid of the two), when a query arrives at the GraphQL server, it resolves the query by reading the payload and fetching the data. Then it uses the schema to return the data in the correct format to the client.

This clearly defined schema structure is what helps GraphQL to be transport-layer agnostic (TCP, Websockets, etc. — it’s all good) and database agnostic (MySQL, MongoDB, Oracle, etc.).

Likewise, if GraphQL is being implemented over multiple systems (as is likely the case in larger corporations with lots of sprawling legacy systems and APIs), it can neatly pull only the requested information from all the various endpoints, and resolve it into one, clean response, laid out by the schema.

Resolvers: How GraphQL Fetches the Data for Its Query (or Mutation) Field

**** Sample Query and the Resolvers Corresponding to Each Field ****query { Student(id:1){ 
firstName
lastName
}
}
Resolvers:Student(id: String!): Student
firstName: (student: Student!) String
lastName: (student: Student!) String

GraphQL Client Libraries

  1. building and sending an HTTP request (fetch in JavaScript),
  2. receiving and parsing the response,
  3. storing the data (locally or persisted),
  4. and finally displaying the data in the UI,

clients can declaratively fetch the data by

  1. describing the data requirements
  2. displaying the returned data in the UI

Complexity and data storage are pushed to the server-side of the application, which is better suited to take care of the heavy computation work, and the frontend is free to do what it was designed to do: show that data to users quickly in a way they can understand.

What I’ve described above is what GraphQL libraries like Apollo and Relay were designed to do. They abstract away the infrastructure implementation of connecting the backend services so developers can focus on the important parts of their application.

In a future post, I’ll go in-depth about using Apollo with GraphQL in a JavaScript project, but this is a post about what exactly GraphQL is and how it does what it does.

More About GraphQL

GraphQL and the Client Side

Directly Sending Queries and Mutations Sans HTTP Requests

GraphQL allows for fetching data in a declarative manner. Instead of making low-level HTTP calls, a client can simply query for the data it needs and GraphQL takes care of the request and response handling for you.

View Layer Integrations & UI Updates

Once the GraphQL client has received and handled the response, there’s a number of ways the UI can be updated to reflect the data. If you’re using React, the GraphQL clients make use of higher-order component concepts (when a function takes one component and returns a new component) to fetch the data make it available to your components in their props.

Client Side Caching

Typically, you’ll want to maintain some kind of a cache or data previously fetched from the server, it’s critical to having a good user experience and shorter load times as they’re interacting with the UI. However, storing the data exactly as it’s resolved from the GraphQL client won’t be the most efficient way to hold it for most applications.

Normalizing the data (flattening nested query results) so that the store only contains individual records that can be referenced with a unique global ID is a better option for quickly retrieving only the necessary data when the same query is made in the future.

Validating & Optimizing Queries Based on the Schema

Also, since the schema contains all the information about what a client could do with a GraphQL API, the build environment can parse the GraphQL code that’s in the project and compare it against the schema’s information. This makes for catching errors and typos much earlier in the process easier (and less likely to happen in the hands of users).

Likewise, UI code and data requirements can actually be written side-by-side in some languages like JavaScript, which makes it easier for developers to see that the right data ends up with the right parts of the UI.

GraphQL and the Server Side

GraphQL Query Execution

For starters, GraphQL uses a simple algorithm for how it changes its queries into results. It traverses the query field by field, executing ‘resolvers’ for each field. If a parent resolver function is required by a child, the parent query will resolve first and pass its result to the child for use in its own query. Finally, once the execution algorithm is done, it forms all the data into the correct shape and returns it.

**** Sample Query and Execution Algorithm ****type Query {
director(id: ID!): Director
}
type Director {
movies: [Movie]
}
type Movie {
title: String
description: String
}
**** Sample Query to the Server ****query { director(id: "2wsx3edc")
{ movies
{
title
description
}
}
}
**** Execution Algorithm Visualized ****Query.director(root, { id:"2wsx3edc" }, context) -> director
Director.movies(director, null, context) -> movies
for each movie in movies
Movie.title(movie, null, context) -> title
Movie.description(movie, null, context) -> description

Batched Query Resolving

GraphQL also offers the ability to make data fetching smarter, if multiple similar calls will be made to the server in one query.

In JavaScript, a utility called DataLoader can be used to wrap the fetching function, which will wait for all the resolvers to run, then make sure to only fetch each item once.

**** Sample Query and API Calls ****query{ movies
{ title
director
{
firstName
lastName
}
}
}
// Regardless of the fact that the API is being called for the same // piece of data multiple times, the query executes for the director // infofetch('/directors/1')
fetch('/directors/2')
fetch('/directors/2')
fetch('/directors/1')
fetch('/directors/1')
**** Sample API Calls with DataLoader****directorLoader = new DirectorLoader()// Queue up all the fetchesdirectorLoader.load(1);
directorLoader.load(2);
directorLoader.load(2);
directorLoader.load(1);
// Then the loader only makes the necessary amount of calls for each // unique piece of informationfetch('/directors/1')
fetch('/directors/2')

GraphQL Tooling and Its Ecosystem

GraphQL Introspection

The designers of a schema obviously know what fields are available, but clients can query GraphQL using the __schema meta field available on the root type of a Query to find out too. This is a powerful technique that can be used to provide many interesting, useful features.

**** Introspection Query and Return Information ****query{ 
__schema {
types
{
name
}
}
}
Schema Definition:type Query {
director(id: ID!): Director
}
type Director {
movies: [Movie]
}
type Movie {
title: String
description: String
}
Results:{
"data": {
"__schema": {
"types": [
{
"name": "Query"
},
{
"name": "Director"
},
{
"name": "Movie"
},
{
"name": "ID"
},
{
"name": "String"
},
{
"name": "__Schema"
},
{
"name": "__Type"
},
{
"name": "__TypeKind"
},
{
"name": "__Field"
},
{
"name": "__InputValue"
},
{
"name": "__EnumValue"
},
{
"name": "__Directive"
},
{
"name": "__DirectiveLocation"
}
]
}
}
}

GraphiQL & GraphQL Playground

Finally, there are two very useful GraphQL IDEs I’m familiar with. The first is GraphiQL, which is a JavaScript, in-browser IDE that’s easy to install and use in projects (it also comes pre-bundled with Apollo for even easier use).

The second is GraphQL Playground, which can be downloaded as a desktop app or used on its website. It incorporates some of the same components as GraphiQL, but boasts additional features like automatic schema reloading, query history, the ability to work with multiple GraphQL APIs at once, interactive schema documentation and more.

In short, both are excellent tools, that allow you to debug and try queries on a GraphQL server without having to write queries over curl.

In Conclusion

Personally, I haven’t used it for very long yet, but I’m already loving it, and I’ll be sure to write a blog post soon about how to implement it with Apollo and React.

Thanks for reading, and claps are very appreciated!

If you enjoyed reading this, you may also enjoy some of my other blogs:

Staff Software Engineer, previously a digital marketer. Frontend dev is my focus, but always up for learning new things. Say hi: www.paigeniedringhaus.com