Practice GraphQL Queries With the State of JavaScript API

Avatar of Sacha Greif
Sacha Greif on

Learning how to build GraphQL APIs can be quite challenging. But you can learn how to use GraphQL APIs in 10 minutes! And it so happens I’ve got the perfect API for that: the brand new, fresh-of-the-VS-Code State of JavaScript GraphQL API.

The State of JavaScript survey is an annual survey of the JavaScript landscape. We’ve been doing it for four years now, and the most recent edition reached over 20,000 developers.

We’ve always relied on Gatsby to build our showcase site, but until this year, we were feeding our data to Gatsby in the form of static YAML files generated through some kind of arcane magic known to mere mortals as “ElasticSearch.”

But since Gatsby poops out all the data sources it eats as GraphQL anyway, we though we might as well skip the middleman and feed it GraphQL directly! Yes I know, this metaphor is getting grosser by the second and I already regret it. My point is: we built an internal GraphQL API for our data, and now we’re making it available to everybody so that you too can easily exploit out dataset!

“But wait,” you say. “I’ve spent all my life studying the blade which has left me no time to learn GraphQL!” Not to worry: that’s where this article comes in.

What is GraphQL?

At its core, GraphQL is a syntax that lets you specify what data you want to receive from an API. Note that I said API, and not database. Unlike SQL, a GraphQL query does not go to your database directly but to your GraphQL API endpoint which, in turn, can connect to a database or any other data source.

The big advantage of GraphQL over older paradigms like REST is that it lets you ask for what you want. For example:

query {
  user(id: "foo123") {
    name
  }
}

Would get you a user object with a single name field. Also need the email? Just do:

query {
  user(id: "foo123") {
    name
    email
  }
}

As you can see, the user field in this example supports an id argument. And now we come to the coolest feature of GraphQL, nesting:

query {
  user(id: "foo123") {
    name
    email
    posts { 
      title
      body
    }
  }
}

Here, we’re saying that we want to find the user’s posts, and load their title and body. The nice thing about GraphQL is that our API layer can do the work of figuring out how to fetch that extra information in that specific format since we’re not talking to the database directly, even if it’s not stored in a nested format inside our actual database.

Sebastian Scholl does a wonderful job explaining GraphQL as if you were meeting it for the first time at a cocktail mixer.

Introducing GraphiQL

Building our first query with GraphiQL, the IDE for GraphQL

GraphiQL (note the “i” in there) is the most common GraphQL IDE out there, and it’s the tool we’ll use to explore the State of JavaScript API. You can launch it right now at graphiql.stateofjs.com and it’ll automatically connect to our endpoint (which is api.stateofjs.com/graphql). The UI consists of three main elements: the Explorer panel, the Query Builder and the Results panels. We’ll later add the Docs panels to that but let’s keep it simple for now.

The Explorer tab is part of a turbo-boosted version of GraphiQL developed and maintained by OneGraph. Much thanks to them for helping us integrate it. Be sure to check out their example repo if you want to deploy your own GraphiQL instance.

Don’t worry, I’m not going to make you write any code just yet. Instead, let’s start from an existing GraphQL query, such as the one corresponding to developer experience with React over the past four years.

Remember how I said we were using GraphQL internally to build our site? Not only are we exposing the API, we’re also exposing the queries themselves. Click the little “Export” button, copy the query in the “GraphQL” tab, paste it inside GraphiQL’s query builder window, and click the “Play” button.

Source URL
The GraphQL tab in the modal that triggers when clicking Export.

If everything went according to plan, you should see your data appear in the Results panel. Let’s take a moment to analyze the query.

query react_experienceQuery {
  survey(survey: js) {
    tool(id: react) {
      id
      entity {
        homepage
        name
        github {
          url
        }
      }
      experience {
        allYears {
          year
          total
          completion {
            count
            percentage
          }
          awarenessInterestSatisfaction {
            awareness
            interest
            satisfaction
          }
          buckets {
            id
            count
            percentage
          }
        }
      }
    }
  }
}

First comes the query keyword which defines the start of our GraphQL query, along with the query’s name, react_experienceQuery. Query names are optional in GraphQL, but can be useful for debugging purposes.

We then have our first field, survey, which takes a survey argument. (We also have a State of CSS survey so we needed to specify the survey in question.) We then have a tool field which takes an id argument. And everything after that is related to the API results for that specific tool. entity gives you information on the specific tool selected (e.g. React) while experience contains the actual statistical data.

Now, rather than keep going through all those fields here, I’m going to teach you a little trick: Command + click (or Control + click) any of those fields inside GraphiQL, and it will bring up the Docs panel. Congrats, you’ve just witnessed another one of GraphQL’s nifty tricks, self-documentation! You can write documentation directly into your API definition and GraphiQL will in turn make it available to end users.

Changing variables

Let’s tweak things a bit: in the Query Builder, replace “react” with “vuejs” and you should notice another cool GraphQL thing: auto-completion. This is quite helpful to avoid making mistakes or to save time! Press “Play” again and you’ll get the same data, but for Vue this time.

Using the Explorer

We’ll now unlock one more GraphQL power tool: the Explorer. The Explorer is basically a tree of your entire API that not only lets you visualize its structure, but also build queries without writing a single line of code! So, let’s try recreating our React query using the explorer this time.

First, let’s open a new browser tab and load graphiql.stateofjs.com in it to start fresh. Click the survey node in the Explorer, and under it the tool node, click “Play.” The tool’s id field should be automatically added to the results and — by the way — this is a good time to change the default argument value (“typescript”) to “react.”

Next, let’s keep drilling down. If you add entity without any subfields, you should see a little squiggly red line underneath it letting you know you need to also specify at least one or more subfields. So, let’s add id, name and homepage at a minimum. Another useful trick: you can automatically tell GraphiQL to add all of a field’s subfields by option+control-clicking it in the Explorer.

Next up is experience. Keep adding fields and subfields until you get something that approaches the query you initially copied from the State of JavaScript site. Any item you select is instantly reflected inside the Query Builder panel. There you go, you just wrote your first GraphQL query!

Filtering data

You might have noticed a purple filters item under experience. This is actually they key reason why you’d want to use our GraphQL API as opposed to simply browsing our site: any aggregation provided by the API can be filtered by a number of factors, such as the respondent’s gender, company size, salary, or country.

Expand filters and select companySize and then eq and range_more_than_1000. You’ve just calculated React’s popularity among large companies! Select range_1 instead and you can now compare it with the same datapoint among freelancers and independent developers.

It’s important to note that GraphQL only defines very low-level primitives, such as fields and arguments, so these eq, in, nin, etc., filters are not part of GraphQL itself, but simply arguments we’ve defined ourselves when setting up the API. This can be a lot of work at first, but it does give you total control over how clients can query your API.

Conclusion

Hopefully you’ve seen that querying a GraphQL API isn’t that big a deal, especially with awesome tools like GraphiQL to help you do it. Now sure, actually integrating GraphQL data into a real-world app is another matter, but this is mostly due to the complexity of handling data transfers between client and server. The GraphQL part itself is actually quite easy!

Whether you’re hoping to get started with GraphQL or just learn enough to query our data and come up with some amazing new insights, I hope this guide will have proven useful!

And if you’re interested in taking part in our next survey (which should be the State of CSS 2020) then be sure to sign up for our mailing list so you can be notified when we launch it.

State of JavaScript API Reference

You can find more info about the API (including links to the actual endpoint and the GitHub repo) at api.stateofjs.com.

Here’s a quick glossary of the terms used inside the State of JS API.

Top-Level Fields

  • Demographics: Regroups all demographics info such as gender, company size, salary, etc.
  • Entity: Gives access to more info about a specific “entity” (library, framework, programming language, etc.).
  • Feature: Usage data for a specific JavaScript or CSS feature.
  • Features: Same, but across a range of features.
  • Matrices: Gives access to the data used to populate our cross-referential heatmaps.
  • Opinion: Opinion data for a specific question (e.g. “Do you think JavaScript is moving in the right direction?”).
  • OtherTools: Data for the “other tools” section (text editors, browsers, bundlers, etc.).
  • Resources: Data for the “resources” section (sites, blogs, podcasts, etc.).
  • Tool: Experience data for a specific tool (library, framework, etc.).
  • Tools: Same, but across a range of tools.
  • ToolsRankings: Rankings (awareness, interest, satisfaction) across a range of tools.

Common Fields

  • Completion: Which proportion of survey respondents answered any given question.
  • Buckets: The array containing the actual data.
  • Year/allYears: Whether to get the data for a specific survey year; or an array containing all years.