An Introduction To GraphQL

9 min read - 18 Jul, 2022
An Introduction To GraphQL
Table Of Contents

In this article, you will learn what GraphQL is and why it is getting so much attention from developers and discuss how it differs from REST by exploring the different concepts, design principles, pros and cons of GraphQL.

Introduction

GraphQL (Graph Query Language) is not a database query language like SQL (Structured Query Language) but an approach to client-server communication. It is a query language for your APIs and runtime for executing queries. It isn't tied to any specific database, technology or language and, is instead backed by your existing code and data. It prioritizes giving clients only the data they request. It was developed at Facebook to make APIs fast, flexible, and developer-friendly.

GraphQL is transport agnostic but is typically served over HTTP.

The GraphQL specification describes the capabilities and characteristics of the language and serves as a guideline for all the implementation of GraphQL. When the spec was released, the creators of GraphQL also shared a reference implementation of the GraphQL specification (graphql-js), designed for running GraphQL in a Node.js environment. The goal of this reference implementation is not to mandate which language you use to implement your service. A GraphQL implementation can be written with any programming language, and integrated with any type of database, as long as it follows the spec. Some of the open-source implementation of GraphQL written in various languages are listed in this website.

GraphQL Server

A GraphQL server is a server-side implementation of the GraphQL spec. It is language and transport agnostic which means that it can be implemented with any programming language and can be served over any protocol. GraphQL servers are composed of two main parts: Schema and Resolvers. GraphQL Schema defines the shape of the data or API and GraphQL Resolver is function that populates every field in the schema so that GraphQl Server can respond to the requests for that data.

Example:

  • GraphQL Schema

    type User {
      id: ID!
      name: String
    }
    
    type Query {
      user(id: ID!): User
      users: [User]
    }
    
  • GraphQL Resolver Function

    const resolvers = {
      Query: {
        user(parent, args, context, info) {
          return db.users.find((user) => user.id === args.id)
        },
        users() {
          return db.users
        },
      },
    }
    

GraphQL Client

GraphQL Client is basically a code that makes a request (with queries or mutations) to GraphqQL server. There are many powerful GraphQL Clients like Apollo GraphQL and Relay which handle batching and catching. But those clients are not needed just to make a request to the GraphQL Server. A simple curl command or fetch api is sufficient to make a request.

curl -X POST \
-H "Content-Type: application/json" \
-d '{"query": "{ name }"}' \
http://localhost:4000/graphql
const name = await fetch("/graphql", {
  method: "POST",
  headers: {
    "Content-Type": "application/json",
  },
  body: JSON.stringify({ query: `{ name }` }),
}).then((response) => response.json())

Design principles

  • Hierarchical

    GraphQL queries are hierarchical. Fields are nested within other fields and the data returned follows the shape of the query.

    Let's take an example by querying info about a user.

    • Here the following query is asking for the fullname, age and blogs (title and slug fields only) fields of a user with id "01".

      {
        user(id: "01") {
          fullName
          age
          blogs {
            title
            slug
          }
        }
      }
      
    • Here the response follows the shape of the query and returns fullname, age and blogs (title and slug only) associated with the user of id "01".

      {
        "data": {
          "user": {
            "fullName": "Shrek",
            "age": 80,
            "blogs": [
              {
                "title": "How to pet dog",
                "slug": "/hot-to-pet-dog"
              },
              {
                "title": "How to pet cat",
                "slug": "/hot-to-pet-cat"
              }
            ]
          }
        }
      }
      
  • Strongly typed

    A GraphQL server is backed by the GraphQL Type System. The type system is used to determine if a query is valid. The type system also describes the input types of query variables to determine if values provided at runtime are valid. It can be ensured that the given query is both syntactically correct and valid within the GraphQL type system at development time.

    type User {
      id: String!
      fullName: String!
      age: Int!
      blogs: [Blog]
    }
    

    Above example creates User Object type with fields fullName as String, age as Int and blogs as array of Blog.

  • Introspective

    A GraphQL server supports introspection over its schema. Introspection is the ability to query which resources are available in the current API schema. GraphQL Client can query the type system using the GraphQL syntax itself.

    Let's take an example of an app which has a User Object type as.

    type User {
      id: String
      name: String
    }
    
    • The following query can be used to find more about User type.

      {
        __type(name: "User") {
          name
          fields {
            name
            type {
              name
            }
          }
        }
      }
      

    • Reponse:

      {
        "__type": {
          "name": "User",
          "fields": [
            {
              "name": "id",
              "type": { "name": "String" }
            },
            {
              "name": "name",
              "type": { "name": "String" }
            }
          ]
        }
      }
      
  • Product-centric

    GraphQL is unapologetically driven by the requirements of views and the front-end engineers that write them. We start with their way of thinking and requirements and build the language and runtime necessary to enable that.

  • Client-specified response

    A GraphQL response contains exactly what a client asks for and no more. In GraphQL, the specification for queries are encoded in the client rather than the server. Client is responsible for specifying how it will comsume the capabilities published by a GraphQL service.

Why use GraphQL ?

  • No over-fetching

    With RESTful APIs, you need to fetch the complete response just to use some fields from the response. But a GraphQL response contains exactly what a client asks for and no more.

    Suppose you are building an app and you need just the title and slug of all the blogs you have written. With RESTful APIs, you have to fetch all the info about all of those blogs. But GraphQL lets you specify exact fields and types to fetch.

    Response examples:

    REST Response Demo

    GraphQL Response Demo

    • No multiple roundtrips

      With RESTful APIs, you need multiple requests to fetch related or hierarchical data. You send request to the server, the server returns the id and then you use that id to send another request to the server. But with GraphQL, you can use nested queries to fetch such related data in a single request.

      Suppose in your blog app you need the name and email of the author of a blog with specific id. With RESTful APIs, you have to first fetch the blog resource (which has the author id) and then fetch the user resource using that author id. But with GraphQL, you can specify you also want to fetch the name and email of the author.

      Response examples:

      REST Response Demo

      GraphQL Response Demo

    • Versioning is not required

      In REST architecture, new versions (/v1, /v2, /v3) need to be created as APIs evolve and structure of response changes. This leads to confusions and challenges down the line. In GraphQL, there is no need to maintain versions. You can just add the new fields and deprecate the old fields in the GraphQL Schema.

      type ExampleType {
        oldField: String @deprecated(reason: "Use `newField`.")
        newField: String
      }
      
    • Better performance

      As discussed above, GraphQL reduces the size of the response by allowing us to specify required fields and minimizes the roundtrips to the server by allowing us to use nested queries. This helps save bandwidth and improve the performance of client-side applications.

GraphQL vs REST

REST (Representational State Transfer) is a software architectural style for designing stateless web APIs whereas GraphQL (Graph Query Language) is a query language and a server-side runtime for executing queries.

Basis GraphQL REST
Description A query language for APIs and a server-side runtime An architectural style for designing APIs
Caching No HTTP Caching Supports HTTP Caching
Versioning Versioning is discouraged Versioning is common
HTTP Methods Only POST ( sometimes GET ) is used All HTTP methods are used
HTTP Status Codes Always returns an HTTP Status code of 200 (even on error) Returns different HTTP Status codes based on type and completion of request
Validation Built-in validation No Built-in validation
Documentation Self documenting No self documenting
Shape of Response Determined by client Determined by server