Photo by Giorgio Dell'Erba on Unsplash

Building a simple GraphQL server

Gene Kuo
6 min readJun 29, 2019

--

In this article, we will first understand what GraphQL is when designing APIs on a software architecture. we will then get to know the concepts and the GraphQL Query operation that we can utilize to design and implement the APIs per our needs. Finally, we will build a rather simple GraphQL server based on what we have learned in this article with the help of Apollo, and test it through Apollo GraphQL Playground.

What is GraphQL?

When designing network communication between client and server, REST has been one of the most popular choices in the software industry. In REST, it enables applications to communicate with each other by using HTTP with URLs and HTTP methods. However, this trend has been changing to Facebook’s GraphQL.

GraphQL went open source in 2015. Before that, Facebook used it internally, for their mobile applications since 2012. It gives clients more control over what specific data to request for, which is more difficult with a REST architecture, in which the RESTful backend defines the data available for each resource on each URL and the frontend has to request all the information at once. In that case, the client will overfetch data if only part of it is needed. That gets worse if the data the client wants needs multiple RESTful requests or the backend has to design a waterfall network requests to fulfill it.

GraphQL is a query language specification on the server-side and client-side that lets the client decide which information it needs by making a single request to the server and reduces the network usage dramatically.

GraphQL operations

A GraphQL operation can be one of a query (read), mutation (write), or subscription (continuous read). Each operation needs to be constructed to a string according to the GraphQL language specification. When the operation reaches the backend GraphQL server, it is interpreted against the GraphQL schema there, and resolved with data for the frontend application. The GraphQL does not limit the the use of network protocol and payload format. However, HTTP protocol and JSON format are the most popular.

GraphQL query operation

The following listing shows a GraphQL query and its result in action:

// A GraphQL query
author(id: "5") {
id
name
url
articles(limit: 2) {
name
urlstring:
}
}
// a GraphQL query result
{
"data": {
"author": {
"id": "5",
"name": "Gene Kuo",
"url": "https://example.com/authors/5",
"articles": [
{
"name": "Building a simple GraphQL server",
"urlstring": "https://example.com/articles/1",
},
...
]
}
}
}

This single query operation requests multiple resources (author, articles) and their specific fields and nested fields the client needs (name, url, …) at once without considering the entire entities has more fields. However, in a REST architecture, the client might need two waterfall requests to get the specific data it needs. In short, the server application defines a GraphQL schema, where it specifies all available data with hierarchy and types, and a client application only queries the required data.

In the above example, the author is an object in GraphQL. Objects hold data about an entity. The data (id, name, url) is accessed using field in GraphQL, just like properties of an object in OO concept. An object can also contains other objects as fields. We can also construct a query by passing arguments to various fields. These arguments can be of different types, such as String, enumerations with fixed set of options, integers and booleans.

Aliases and fragments

When we want to query data about multiple identical objects, we have to use aliases in GraphQL. For example, if we want to request two GitHub organizations through GraphiQL, we construct the following query operation using aliases.

We can also use GraphQL fragment to extract the reusable parts.

{
container: organization(login: "docker") {
...organizationFields
}
social: organization(login: "facebook") {
...organizationFields
}
}

fragment organizationFields on Organization {
name
url
}

In this case, we specify the type of the object on which the fragment should be used, that is, Organization. The Organization type is defined by the schema which exposes the GitHub’s GraphQL API. We can say that GraphQL schema defines GraphQL graph that is accessible via the GraphQL API using queries and mutations.

Variables

We can construct a query like a function by using variables in GraphQL.

The content in the “Query Variables” panel provides values for the organization variable as an argument for the query, The exclamation point for the arguments type of String in the query indicates that the argument is “required” to fulfill the query. When we use variables, we have to use query statement like the above, as opposed to the previous examples, which are shorthand queries. The query is called operation type in GraphQL. There are other type of operations, such as mutation. We can also specify an operation name for the a query, resulting in a named query, which provides clarity about our intention.

query getOrganization ($organization: String!) {
organization(login: $organization) {
name
url
}
}

Querying nested objects

Since the GraphQL schema implements an entire graph, the GraphQL also allows us to access nested objects with a query operation.

Directives

GraphQL directives can be applied to objects and fields. Here we will learn to use two types of directives: include directive, which includes the field when the Boolean is true; and the skip directive, which is the opposite of the former one. We can use the GraphQL directives to apply conditional structures to our queries this way.

Implementing a GraphQL server

We are now going to implement a server-side architecture using GraphQL and Apollo server. Apollo server builds on GraphQL language to simplify building GraphQL servers in JavaScript.

First of all, we have to install some dependencies in a Node.js project. Here we will use Apollo with Express, however, there are also other middleware that can be chosen from, such as Hapi and Koa.

npm install apollo-server apollo-server-express --save
npm install express graphql --save

We can then edit src/index.js as in the following listing. In the listing, the GraphQL schema defines all available data for reading and writing via GraphQL. It consists of type definitions with a mandatory Query type for reading data, followed by fields and nested objects’ types which defines various scalar types as their fields. The scalar types can be strings (String), booleans (Booleans), integers (Integer) and so on. The resolvers are the functions that return data for fields in the schema. We are now hardcoded the data in the resolver, however, the data can come from any datasource.

import express from 'express';
import { ApolloServer, gql } from 'apollo-server-express';

const app = express();
const schema = gql`
type Query {
user: User
}

type User {
username: String!
}
`;

const resolvers = {
Query: {
user: () => {
return {
username: 'Gene Kuo'
};
},
},
};

const server = new ApolloServer({
typeDefs: schema,
resolvers,
});

server.applyMiddleware({
app,
path: '/my-qraphql'
});

app.listen({ port: 8000 }, () => {
console.log('My Apollo server listening on http://localhost:8000/my-qraphql');
});

Now, we can start our GraphQL server with npm start, and verify it work using GraphQL Playground by pointing to the endpoint in a browser at http://localhost:8000/my-qraphql.

This completes our rather simple GraphQL implementation.

Conclusion

In this article, we only learned one of the GraphQL operations: Query, and immediately implemented a simple GraphQL server with a simple schema and resolver. We tested it using Apollo Playground to get a feel about how to consume a GraphQL API with its flexibility.

To go further, we have several points to consider, such as understanding more operations: mutation and subscription, and their usage patterns, handling complex schema and resolvers, designing schema stitching, connecting datasource, creating a GraphQL client, handling validations and errors, implementing authentication and authorization, designing pagination and so on.

Thanks for reading.

--

--

Gene Kuo

Solutions Architect, AWS CSAA/CDA: microservices, kubernetes, algorithms, Java, Rust, Golang, React, JavaScript…