In this article, we’ll walk through setting up a project, creating a simple GraphQL server, building a complex schema, and creating mutations.
GraphQL is a query language for application programming interfaces (APIs). In simple terms, it is a syntax to define the data structure you need.
We already have a REST API, so how is GraphQL different? Like REST API, GraphQL is a stateless, client-independent API for exchanging data. However, its advantage is higher flexibility.
REST API has some serious performance issues when it comes to customizing API calls. This normally affects your application’s mobile users by causing content to load slowly. This is normally due to the time it takes to return data that is of little or no use along with the requested data.
To fix the issue of longer load times, developers must define new endpoints for each data structure requested, or use request parameters, which may be confusing to the front-end developers while sending the request as they might miss passing the right request parameters or interchange the use of parameters. GraphQL solves this issue by having one single endpoint and a structure that allows requested data to be passed as queries.
REST API has a large user base, but GraphQL is gaining popularity. Because of its improved performance, some large companies — such as Shopify and GitHub — are starting to offer GraphQL APIs for developers.
In this article, we’ll show you how to implement a GraphQL server with Node.js and Express. We will walk through setting up a project, creating a simple GraphQL server, building a complex schema, and creating mutations. Here is the repository for the codebase we will use.
How GraphQL Works
GraphQL only needs a single endpoint. This endpoint takes the query with data customizations as the request body, which can be dynamic according to the needs of the data requested.
Other than the one endpoint, we’ll send only one kind of request: a POST
request to the ‘/graphql’ URL. That is because with POST
requests, you can add a request body containing the query to perform all the other data manipulations.
Structure of a GraphQL Query
A typical GraphQL query has three parts: operation type, operation endpoint, and requested fields:
{
*operation type* {
*endpoint* {
*requested fields*
}
}
}
Operation type, in turn, has three types:
- Query: Used to retrieve specific data. Acts like a "
GET
" request. - Mutation: Used to manipulate data. Acts like "
POST
", "PUT
", "PATCH
", or "DELETE
". - Subscription: Used to set up a real-time connection via
WebSocket
s.
That’s enough theory. Let's get our hands code dirty!
Project Setup
You can implement a GraphQL server with any web server programming language, like Java, Ruby, Python, and C#, to name a few.
For the purpose of this demonstration, I’ll use Node.js and Express to set up a GraphQL server. If you want to follow this article using Node.js, and if you haven’t installed it in your system, you can download it from the official Node.js website.
Open your desired command prompt and check if Node.js and NPM are properly installed using the commands below:
node -v
npm -v
If you see their respective version numbers, then they are successfully installed.
Create a new empty project folder with an appropriate name:
mkdir graphql-demo
Go to that directory and initiate your Node.js project by creating a ‘package.json’ file using the command:
npm init
Create a new server.js file in the project directory using the following commands:
For Windows:
type nul > server.js
For Mac and Linux:
touch server.js
Add the required NPM packages graphql, express, and express-graphql
to the project using the command:
npm install graphql express express-graphql –save
Now that we have set up the project, we are ready to implement our first GraphQL server.
Creating a Simple GraphQL Server
To handle a GraphQL query, we need a schema that defines the operation type and the API endpoint. We also need a resolver to map to the endpoint from the request. Here’s how a simple "Hello World!
" program using GraphQL without an Express server looks:
var { graphql, buildSchema } = require('graphql');
var schema = buildSchema(`
type Query {
hello: String
}
`);
var root = {
hello: () => {
return 'Hello world!';
},
};
graphql(schema, '{ hello }', root).then((response) => {
console.log(response);
});
The schema defines how the client can access the data. It gets validated on each API call and returns the data only if the validation is successful, else it returns an error.
The resolver consists of mapping actions to the endpoints defined in the query. As the query grows, the resolver will also grow.
Run the following command to see the GraphQL response:
node server.js
If you get the following response, you just ran your first GraphQL query:
{data: { hello: ‘Hello world!’} }
Let’s try the same program as above, but this time, let’s spin up an Express server. Change your server.js code to the following code:
var express = require('express');
var { graphqlHTTP } = require('express-graphql');
var { buildSchema } = require('graphql');
var schema = buildSchema(`
type Query {
hello: String
}
`);
var root = {
hello: () => {
return 'Hello world!';
},
};
var app = express();
app.use('/graphql', graphqlHTTP({
schema: schema,
rootValue: root,
graphiql: true,
}));
app.listen(4000);
console.log('Running a GraphQL API server at http://localhost:4000/graphql');
Express spins up a server with GraphQL and with ‘graphiql
’ set to ‘true
’. It then opens an interactive graphical interface for trying out GraphQL queries. Bring up the server using the command:
node server.js
Open your desired browser and navigate to http://localhost:4000/graphql. You’ll be able to see an interface that lets you enter queries:
Congratulations — you just executed a GraphQL query using an Express server!
Building a Complex Schema
Let’s update the schema for sample data like below:
var heroes = [
{
id: 1,
name: 'Iron Man',
age: '40',
ability: 'Flying, Rockets'
},
{
id: 2,
name: 'Dr. Strange',
age: '30',
ability: 'Magic'
},
{
id: 3,
name: 'Hulk',
age: '45',
ability: 'Anger'
},
{
id: 4,
name: 'Ant man',
age: '26',
ability: 'Shrink'
},
{
id: 5,
name: 'Black Widow',
age: '25',
ability: 'Spy'
}
];
In addition to using the primitive types, like integer and string, we can also define our own type and use it for other query parameters:
var schema = buildSchema(`
type Query {
hero(id: Int!): Person
},
type Person {
id: Int
name: String
age: Int
ability: String
}
`);
Here, ‘Person
’ is a user-defined type for the parameter ‘hero
’. We have to update the resolver like below:
var root = {
hero: getHero,
};
Let’s spin up the server again using the command:
node server.js
Navigate to http://localhost:4000/graphql and enter the following query:
query getHero($heroId: Int!) {
hero(id: $heroId) {
id
name
age
ability
}
}
If you run the query, you’ll get the following error:
{
"errors": [
{
"message": "Variable /"$heroId\" of required type \"Int!\" was not provided.",
"locations": [
{
"line": 1,
"column": 15
}]
}]
}
As the error states, we are missing the variable $heroId
. Let’s quickly create a variable by clicking the Query Variables tab at the bottom left corner of the GraphQL interface.
Now, if you press run again, you can see the response data of that particular hero whose id we passed as a parameter:
Using Mutations
We have seen how to retrieve data using GraphQL. Now, let’s see how to update data by using another operator type called mutations.
Update the build schema by defining a mutation:
var schema = buildSchema(`
type Query {
hero(id: Int!): Person
},
type Person {
id: Int
name: String
age: Int
ability: String
}
type Mutation {
updateHero(id: Int!, name: String!, ability: String): Person
}
`);
We can see the mutation takes three parameters: ‘id
’, ‘name
’, and ‘ability
’, and returns data of type ‘Person
’. We also have to create a new function to update the data. We also need to update the resolver to point to that function:
var updateHero = function ({ id, name, ability }) {
heros.map(hero => {
if (hero.id === id) {
hero.name = name;
hero.age = ability;
return hero;
}
});
return heros.filter(hero => hero.id === id)[0];
}
var root = {
hero: getHero,
updateHero: updateHero
};
Let’s run the server file again using:
node server.js
Navigate to http://localhost:4000/graphql and enter the following query:
mutation updateHero($id: Int!, $name: String!, $ability: String) {
updateHero(id: $id, name:$name, ability: $ability){
name
ability
}
}
Also, define the required parameters in the Query Variables section:
{
"id": 1,
"name": "Captain America",
"ability": "Shield"
}
Click run. We can now see the updated ‘hero
’ data:
{
"data": {
"updateHero": {
"name": "Captain America",
"
Voila! You just updated your data using GraphQL.
How to Reduce Load Times in Your Own Application
GraphQL
empowers developers to ask for exactly what they need and nothing more. This helps trim unwanted API calls, in turn reducing application load times.
Though REST API outmatches GraphQL due to market popularity, GraphQL is gaining support. It will outmatch REST once tools supporting GraphQL are widely available. With support from major organizations like Shopify and GitHub, it is on its way.
To learn more, look at the GraphQL documents.
This article originally appeared as a guest submission on ContentLab.