Software development has evolved as never like before. Technologies and tools are changing rapidly and one must leverage the tools to overcome the limitations of existing ones. In this blog, we are going to discuss GraphQL an API querying language that overcomes the limitations of standard REST API.
Before we begin let’s understand what is an API. An API stands for “Application programming interface” which is nothing but a middle layer between two endpoints. Consider a restaurant and a waiter. You need the waiter to request your order from you, from your table to the kitchen where the chef prepares the food. The same is true with an API. The Waiter (the API) takes your order (the request) from your table to the kitchen (the server) and returns with your food (the response information).
Basically, an API is used to process the request and retrieve it and send back the response from a server. Since the start of modern application development, there are multiple ways you can retrieve information from a server. One of the commonly used and the industrial standard is using a REST API. A REST API is an architecture that uses HTTP protocol to transfer/retrieve data from a server such as GET, POST, PUT, DELETE, and PATCH.
Limitations of REST API
1. Overfetching and under fetching: A REST API usually has a number of endpoints that return the data in a structured manner. The problem is with this approach is you’ll always get the same data whether you requested them or not. Which in turn creates a performance issue when you have to deal with slow internet connections.
2. Minimise API endpoints: Usually, a REST API contains a lot of endpoints which respond to the HTTP methods such as GET, POST, PUT, DELETE, and PATCH. This makes the API so huge and difficult to handle when your application grows.
Why GraphQL?
To solve these problems Facebook developed GraphQL which works completely different as compared to REST. Here the API will be having only one endpoint which gives the data exactly what you have requested with nothing less and nothing more.
So let’s look at an example of how a GraphQL query works versus a REST API query works to get a better idea of the differences between the two. Imagine you have an application that has posts and authors as the resources and each resource contains information like author, author email, author address, post title, post body, publishing date, etc. Now let’s assume you are building a front-end application and you want to display the title of all posts of all authors as quickly as possible.
Typically with a REST API, you’ll have two endpoints such as /authors
and /authors/:id/posts
. So basically you have to send the GET request to the author’s endpoint to get the IDs of the authors and which in turn to make another get requests to posts with specified author id. That means you’ll have to make multiple GET requests to fetch title for a specific author which will give you all the extra bunch of information about the author and the specific posts which we don’t need at the moment.
//GET id's of authors fetch(`/api/authors`) .then(res => res.json()) .then(data => { data.map(item => { ids.push(item[id]) }) }); //GET posts of authors ids.map(id => { fetch(`/api/authors/:${id}/posts`) .then(res => res.json()) .then(data => posts = data); }); //ouput [ {id:1,title:"some title",author:"name",body:"some body",date:"01/01/2020"}, {id:1,title:"some title",author:"name",body:"some body",date:"01/01/2020"}, {id:1,title:"some title",author:"name",body:"some body",date:"01/01/2020"} ]
So, let’s look at a GraphQL query and how it’ll handle the above situation. Basically with GraphQL, you’ll tell the server exactly what you need by composing a single query. You’ll then send the query to the API which has only one endpoint /graphql
to and the GraphQL server parses the request and returns the information which you have asked for.
query{ authors{ posts{ title } } } //output [ { name:"author1", titles:[ "title1","title2","title3" ] }, { name:"author2", titles:[ "title1","title2","title3" ] } ]
So with one single query to the GraphQL server, you are getting the names of all authors and their post titles with no extra information. This is absolutely amazing and the main reason GraphQL growing much faster. This is just the beginning of the graphql and you can do all the things just like in a REST API. Additionally, we can also mutate the query to use different HTTP methods like creating new posts and return the ID of the post, and many more.
Now as you have a basic understanding of GraphQL let’s create a NodeJS application that implements the above author and posts to better understand how you can work with GraphQL in your next project.
Express-graphql server
To begin with create a new empty directory named graphql-blog and run npm init -y
to create a node application.
$ sudo mkdir graphql-blog
$ npm init -y
{
"name": "express-blog",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"keywords": [],
"author": "",
"license": "ISC"
}
Once you have setup the directory and node package.json we can install the required libraries using the command,
$ npm i express express-graphql graphql
Here express is used to create a new HTTP server with express-graphql which is used to implement the graphql functionalities in express and graphql is used as the main graphql dependency.
Also, we can install the library nodemon
to watch the files for changes and reload it whenever required. You can install the package as a dev dependency using
$ npm i --save-dev nodemon
Once you have installed the packages edit the package.json file and add a build script inside the scripts tag and also create the index.js file.
"scripts": { "devStart":"nodemon index.js" },
$ touch index.js
Now that we are done installing the required packages and files we can start building our application. Open up the index.js file and create a basic express application.
var express = require('express'); var { graphqlHTTP } = require('express-graphql'); var { buildSchema } = require('graphql'); const app = express(); app.listen(5000,() => console.log('Running server at http://localhost:5000'));
Now that we are created an express server we can implement the graphql endpoint to make the server responds to the /graphql
endpoint.
const app = express(); const schema = new buildSchema(` type Query{ posts: [Post] } type Post{ id: Int title: String date: String } `) const posts = [ { id: 1, title:'Title 1', date:'27/11/2020', }, { id: 2, title: 'Title 2', date:'27/11/2020', } ] const root = ({ posts: () => { return posts; }, }); app.use('/graphql', graphqlHTTP({ schema, rootValue: root, graphiql: true }))
First of all we have created a new graphqlSchema which is mandatory to query a graphql server. Inside the schema we created a type of Query and added a post object of type Post which in turn return id, title and date from the posts array of object.
Then we have a root value specified as root which acts as a controller to resolve the graphQL queries. Here in the root resolver, we have added a function posts which returns the posts array. Then finally we specified graphiql : true to
visualize the graphiql server in a web browser.
Now, in terminal run the development server using the start script we specified in package.json.
$ npm run devStart
The above command will fire the nodemon and run the index.js file. Now open a web browser and navigate to "localhost:5000/graphql"
to see the result.
So as you can see above we get the information from the posts array which we specified in the schema. To conclude, this is how we can implement a basic graphql server with a node application and query the information from the server. In this example, we queried statically typed information but you can also query from a database and return the data from the root resolver.