DEV Community

Cover image for Why GraphQL is awesome
TJ Bosmans
TJ Bosmans

Posted on

Why GraphQL is awesome

note: this is not a tutorial, there are plenty of those out there that are better than what I could do, I'll share some.

What is GraphQL?

Most beginners will get introduced to REST architecture sooner or later, as it's the cornerstone of data transfer in web services between an API and a client using HTTP methods GET/POST/PUT/DELETE. RESTful designs are commonly used to query and send data between a client (e.g. a browser or an application) and a back end, or a 3rd party API in the form of XML, JSON, HTML or text. In modern programming frameworks and libraries it is straightforward to set up a server in Express, Rails or Django that via controllers provide different endpoints and routes to send requests to with something like Fetch, Axios, Requests, etc.
While straightforward, something feels a little awkward when setting up many controllers that each have different routes and params for GET requests, POST requests etc. Without splitting out even more routes and writing a lot of backend logic, you also can't really choose what you get when querying, it's either all or nothing.

GraphQL solves the above. It is simply a query language (and environment with some tools) that has implementations in all main programming languages. Rather than sending requests to multiple endpoints, requests are made based on types and fields and you get what you ask for, not more, not less.

OK, how do I do this?

Let me show you my favorite way to set up a GraphQL server: in a Node.JS environment using Express and the express-graphql module, which you can find documentation on here.
Much like setting a controller, you can connect an endpoint to a graphql schema using express middleware. The code would look something like this:

const express = require("express");
const { graphqlHTTP } = require("express-graphql");
const schema = require("./schemas");
const app = express();

app.use(
  "/graphql",
  graphqlHTTP({
    schema,
    graphiql: true,
  })
);
Enter fullscreen mode Exit fullscreen mode

note: as we'll see in a moment, a graphql schema is conceptually much like a database schema and will in practical applications in e.g. a MERN app often mirror your database schema somewhat, but much of the power of GraphQL comes from the fact that it is in fact completely independent from the structure of your database and adds another layer to pick and pack and manipulate data prior to sending to a client.

The graphiql: true in the above snippet indicated we'd like to get graphiql in the browser, which is a really nice tool that lets you mock queries to your server. Kinda like you would use Postman but for GraphQL.

Now in the schemas.js file that we brought in above, we would define our Types, and set its Fields; something like this:

const BookType = new GraphQLObjectType({
  name: "Book",
  fields: () => ({
    id: { type: GraphQLID },
    name: { type: GraphQLString },
    genre: { type: GraphQLString },
    author: {
      type: AuthorType,
      resolve(parent, args) {
        //code to lookup author based on ID in the Author database collection
        return Author.findById(parent.authorId);
      },
    },
  }),
});

Enter fullscreen mode Exit fullscreen mode

The above code highlights another neat feature of GraphQL; the Type Book has a field 'author' that can be another Type, basically adding a relational layer on top of a (in this case) non-relational database (MongoDB here).

After defining all the Types and all their fields, we define 1 object that will enable you to query all the data you like. This is called a RootQuery:

const RootQuery = new GraphQLObjectType({
  name: "RootQueryType",
  fields: {
//query for 1 book
    book: {
      type: BookType,
      args: { id: { type: GraphQLID } },
      resolve(parent, args) {
        return Book.findById(args.id);
      },
    },

    //query for a list of books
    books: {
      type: new GraphQLList(BookType),
      resolve(parent, args) {
        return Book.find({});
      },
    },
  },
});
Enter fullscreen mode Exit fullscreen mode

The resolver functions basically hold the code to go get the data, be it through a database mapper like here, or by making an external API call, or any other way you can return data.
Based on the above example, a query for all the books would look like this:

{
 books {
  id
  name
  genre
  author
 }
}
Enter fullscreen mode Exit fullscreen mode

But perhaps you only need the name and the author and you could do this:

{
 books {
  name
  author
 }
}
Enter fullscreen mode Exit fullscreen mode

Or maybe you're looking to show 1 book in specific and you pass it's id as an argument:

{
 book(id: '12345') {
  name
  author
 }
}
Enter fullscreen mode Exit fullscreen mode

OK, let me try this...

Of course, this is just a small teaser. This only shows so far how to make queries. You can also update and delete data by making mutations.
If you like to see the power of GraphQL yourself, I highly recommend looking at the official page. If you would like to see how to use it in a MERN app, including how to make the queries/mutations (making a full CRUD app) from React using the Apollo client, I recommend watching this tutorial.
To me, this is what modern web development looks like.
Happy hacking!

Discussion (0)