DEV Community

Cover image for Starting out with GraphQL
Nočnica Mellifera for Heroku

Posted on

Starting out with GraphQL

What is GraphQL?

GraphQL is a query language for APIs and a runtime for fulfilling those queries with your existing data. By running a GraphQL server (e.g. Apollo GraphQL), your existing applications can send parameterised requests and get back JSON responses.

What is it good for?

Is GraphQL The answer to all of life’s problems? Maaaaaaybe? But it isn’t a database or a web server, the two things its most often confused for. Let’s dive in.

GraphQL is a communication standard. Its goal is to let you request all the data you need with a single fairly compact request. It was born as an attempt to improve on REST APIs for populating web pages with data. The classic conundrum looks like this:

WEBPAGE: When Bob comments on a photo, I want to show a tooltip with profile pics of Alice and Bob’s top 5 mutual friends.

APP: okay, here’s Bob’s ‘user’ record

WEBPAGE: this has all his friend’s IDs, I need their mutual friends.

APP: hey good news I built an endpoint that takes two users IDs and returns their mutual friends

WEBPAGE: Great!

APP: they have 137 mutual friends

WEBPAGE: geez I want the top 5 by date, but… okay, now can I get their profile pictures

APP: sure here’s the first friend’s ‘user’ record

WEBPAGE: I need-

APP: here’s the second friend complete ‘user’ record

WEBPAGE: you don’t just have the photos?

APP: nope! Here’s the third friend’s ‘user’ record. Geez this is taking a while, huh? SOMEone’s on 3g, amirite?

-fin-

What’s wrong with this picture? In general two things:

  • Overfetching: while most REST API’s will have a way to ask for a ‘top 5’, there’s usually no way to ask for some information. We only wanted Bob’s mutual friends, and then after that we only wanted the mutuals photos not their full profiles
  • Multiple round trips: the very last request, for all 5 mutual friends' user profiles could be done in parallel, but all the steps before that would have to happen synchronously, waiting for a full reply before the next step could happen. If you think this isn’t a problem, you need to be a bit better informed about the public’s level of broadband access

In this scenario, no ‘bad engineering’ happened with this REST API, in fact the work’s been done to return filtered and scoped lists for some requests! But it is true that the front-end page team doesn’t have access to set up the exact API endpoints they need. This is an important point and I want to emphasize it a bit.

If you have full access to alter your REST API, you don’t need GraphQL

If your pal, the backend developer, is working with you to set up this feature, they can absolutely set up user/views/top5mutualpics and give you just the data you need, but the trouble starts as your operation grows and features on the front end need to be delivered without API changes. This probably means your org is growing, your user base is growing, and that you expect the frontend to grow and change without updates to your API, so it’s probably a good thing!

Benefits of GraphQL

GraphQL allows you to request data to the depth and in the shape that you need. It also implicitly lets you scope your request to get only the fields you need

{
  hero {
    name
  }
}

The response we get back will be JSON in this shape:

{

  "data": {

    "hero": {

      "name": "R2-D2"

    }

  }

}

This example is done on the lovely Star Wars API (SWAPI) endpoint, check out its GraphQL interface here

So there’s no need to create separate /profile /profile_posts and /profile_vitals endpoints to get more focused versions of the data. The goal here is to have GraphQL "wrap around" your existing REST API end points and provide a new, unified interface that lets me query all the things.

Tips for the beginner writing GraphQL queries

I saw an amazing talk from Sean Grove of One Graph who works on maintaining GraphiQL, the rad graphical explorer for GraphQL. He talked about adding automations to GraphQL to let it point new query writers in the direction of more efficient coding of GraphQL queries. The query language is supposed to be easy, so these points shouldn’t add significantly to the weight of writing new queries.

Optimize with variables

GraphQ: lets you parameterise queries. Here we are making a query asking for a particular hero that matches the film name "NEW HOPE" and the names of their friends:


hero(“NEW HOPE”) {

    name

    friends {

      name

    }

  }

This looks pretty good but updating this query will require some string manipulation by our GraphQL client (e.g. the React web app that will be asking for data). Also, later queries with different parameters will not benefit from any caching, since the GraphQL server will see it as a whole new query. So it’s better to add a variable to a query, then re-use the same query over and over:


query HeroNameAndFriends($episode: Episode) {

  hero(episode: $episode) {

    name

    friends {

      name

    }

  }

}

This example and others in this article are cribbed from the GraphQL learn pages

Now we can update the episode variable and re-run the same query, and it’ll impact the client less AND return faster.

Set defaults for your variables

If you love the other devs on yourself or even future you, you’ll set defaults on your variables to make sure each query succeeds

query HeroNameAndFriends($episode: Episode = JEDI) {
  hero(episode: $episode) {
    name
    friends {
      name
    }
  }
}

Later you can re-use this query as

HeroNameAndFriends('EMPIRE') 

and benefit from caching!

Write more DRY (‘don’t repeat yourself’) queries with fragments

It’s an amazing feature that you get to specify exactly the fields that you want to get back from a GraphQL query, after a while this can get… kinda tedious:

hero(episode: $episode) {
    name
    height
    weight
    pets {

        name

        height

        weight

    }
    friends {

      name

      height

      weight

    }

  }

If this was a query we might be asking for photos, IDs, friends’ IDs, over and over again as the query has more clauses. Surely there’s a way to ask for:

`name`

`height`

`weight`

All at once? Yup!

Define a fragment like so:

fragment criticalInfo on Character {

    name

    height

    weight

}

Note that Character is just a label I’m using in this example, i.e. a character in a story

Now our query is much more compact:

hero(episode: $episode) {

    ...criticalInfo

    pets {

      ...criticalInfo

    }

    friends {

      ...criticalInfo

    }

  }

Ready to dive in and go further?

My next article will cover how to host your first GraphQL server on Heroku, and after that how to build your first service architecture.

Your next step if all this is interesting to you should be to get a full series on GraphQL queries right from the GraphQL team on their learn page.

If you want to really learn GraphQL, I cannot recommend highly enough “Learning GraphQL” by Alex Banks and Eve Porcello.

This and the several articles that will follow it brought to you by my favorite train read the last few weeks.

Top comments (1)

Collapse
 
patarapolw profile image
Pacharapol Withayasakpunt

Truthfully, I only care about GraphQL, only if it can automatically sync with SQL schema and joins, along with projection and WHERE.

Otherwise, I would stick to JSON in REST API.