DEV Community

Cover image for Getting started with GraphQL and Node.js
reymon359 for One Beyond

Posted on • Edited on

Getting started with GraphQL and Node.js

The main purpose of this server-client Node.js project is to help other people understand how GraphQL exposes the data from the Server and the Client fetches it. I have tried to make it as simple as possible- if you want to dive into the code of the project you can find it here.

Now, straight to the point: GraphQL is a query language for APIs developed and open-sourced by Facebook to speed up the request process.

While REST has been a popular way to expose data from a server, instead of having multiple endpoints that return fixed data structures, GraphQL just has a single endpoint and it is the client's job to specify what data it needs from it.

Table of Contents

  • Getting started
  • Define the Schema
  • Add Resolver function
  • Set up the Server
  • Set up the Client
  • Fetching data from the server
  • Displaying the data
  • Conclusion
  • Useful resources
    • Docs πŸ“š
    • Learn πŸ“
    • Tools πŸ”§
    • IDEs πŸ’»
    • Extras 🍍

Getting started

The first step is to download and install Node.js in case you haven't already. Once you have it installed let's begin with the directory structure. The project will be composed of two directories, one for the Client and another for the Server. I have chosen to keep both inside the project root directory but then you can split it into two separate projects or any way you want.

πŸ“ project
β”œβ”€β”€ πŸ“ client
└── πŸ“ server
Enter fullscreen mode Exit fullscreen mode

Now we will initialize the project in the server directory. Change the location to the server folder in your terminal and run npm init to fill in the project info and generate the package.json file. Or npm init -y which tells the generator to use the defaults (instead of asking questions and simply generate an empty npm project without going through an interactive process).

The next step will be to install GraphQL.js and Apollo Server to our server. GraphQL.js will provide two important capabilities:

  • Building a type schema, which we will do in the next step.
  • Serving queries against that type schema.

To install it just run npm install graphql. I am assuming you are using a version of NPM equal or higher than 5.0.0 so you do not need to add --save when installing a dependency to be saved in the package.json.

Apollo Server, on the other hand, will help us to implement the GraphQL functionalities. It is part of the Apollo Data Graph Platform.

Apollo is a platform for building a data graph, a communication layer that seamlessly connects your application clients (such as React and iOS apps) to your back-end services. Is an implementation of GraphQL designed for the needs of product engineering teams building modern, data-driven applications. - Apollo Documentation

What you need to know about Apollo, at least for now, is it’s a community that builds on top of GraphQL and provides different tools to help you build your projects. The tools provided by Apollo are mainly 2: Client and Server.

  • Apollo Client helps your Frontend communicate with a GraphQL API. It has support for the most popular frameworks such as React, Vue, or Angular and native development on iOS and Android.

  • Apollo Server is the GraphQL server layer in your backend that delivers the responses back to the client requests.

Now that you understand Apollo better and why we will use it, let's continue setting up GraphQL.

Define the Schema

A GraphQL Schema is at the core of any GraphQL server implementation. It describes the shape of your data, defining it with a hierarchy of types with fields that are populated from your data source and specifies which queries and mutations are available, so the client knows about the information that can be requested or sent.

For example, if we wanted to build a music application, our simplest schema, usually defined in a schema.graphql file, would contain two Object types: Song and Author like this

type Song {
  title: String
  author: Author
}

type Author {
  name: String
  songs: [Song]
}
Enter fullscreen mode Exit fullscreen mode

Then we would have a Query type to define the available queries: getSongs and getAuthors, each returning a list of the corresponding type.

type Query {
  getSongs: [Song]
  getAuthors: [Author]
}
Enter fullscreen mode Exit fullscreen mode

To keep it as simple as possible our schema will have just a single Query type which will return a String.

type Query {
  greeting: String
}
Enter fullscreen mode Exit fullscreen mode

We can use any programming language to create a GraphQL schema and build an interface around it but as I explained before we will use Apollo server to execute GraphQL queries. So we create a new server.js file in the server directory to define the Schema on it.

πŸ“ project
β”œβ”€β”€ πŸ“ client
└── πŸ“ server
    └── πŸ“„ server.js
Enter fullscreen mode Exit fullscreen mode

Now we install apollo-server running npm install apollo-server

We have to import the tag function gql from apollo-server to parse the schema this way: const {gql} = require('apollo-server'); and then declare a typeDefs constant which is an abstract syntax tree of the Graphql code.

When a GraphQL server receives a query to process it generally comes in as a String. This string must be tokenized and parsed into a representation that the machine understands. This representation is called an abstract syntax tree.

If you want to learn more about abstract syntax trees AST Explorer is an online tool that lets you explore the syntax tree created by a chosen language as a parser.

The server.js file would look like this.

const { gql } = require('apollo-server');

const typeDefs = gql`
  type Query {
    greeting: String
  }
`;
Enter fullscreen mode Exit fullscreen mode

Add Resolver function

Now we have defined our Schema we need a way to answer the client requests for that data; the resolvers.
A resolver is a function that handles the data for each one of the fields of your schema. You can send that data to the client by fetching a back-end database or a third-party API among others.

They have to match the type definitions of the Schema, in our case, we just have one type definition Query which returns a greeting of type String, so we will define a resolver for the greeting field, like so:

const resolvers = {
  Query: {
    greeting: () => 'Hello GraphQL world!πŸ‘‹',
  },
};
Enter fullscreen mode Exit fullscreen mode

As I explained at the beginning we will keep this example as simple as possible but keep in mind that in a real case here is where you have to make the queries to the database, external API, or from wherever which you intend to extract the query data.

Set up the Server

In the same server.js, we define and create a new ApolloServer object passing the Schema (typeDefs) and resolvers as parameters.

const { ApolloServer, gql } = require('apollo-server');

const server = new ApolloServer({ typeDefs, resolvers });
Enter fullscreen mode Exit fullscreen mode

Then calling the listen method we start the server on the port that we specify in the params.

server
  .listen({ port: 9000 })
  .then(serverInfo => console.log(`Server running at ${serverInfo.url}`));
Enter fullscreen mode Exit fullscreen mode

We can also destructure the ServerInfo url when logging it.

server
  .listen({ port: 9000 })
  .then(({ url }) => console.log(`Server running at ${url}`));
Enter fullscreen mode Exit fullscreen mode

The server.js file should look like this right now.

const { ApolloServer, gql } = require('apollo-server');

const typeDefs = gql`
  type Query {
    greeting: String
  }
`;

const resolvers = {
  Query: {
    greeting: () => 'Hello GraphQL world!πŸ‘‹',
  },
};

const server = new ApolloServer({ typeDefs, resolvers });
server
  .listen({ port: 9000 })
  .then(({ url }) => console.log(`Server running at ${url}`));
Enter fullscreen mode Exit fullscreen mode

Now if we run node server/server.js we will finally have our GraphQL server up and runningπŸŽ‰!

You can go and check it on http://localhost:9000/

~/graphql-hello-world-server
> node server/server.js
Server running at http://localhost:9000/
Enter fullscreen mode Exit fullscreen mode

For the first time using GraphQL, you may be thinking what is this application I am seeing in front of me if we have not written a single line of client code?.

The answer to that question is the GraphQL Playground.

graphql-playground

GraphQL Playground is a graphical, interactive, in-browser GraphQL IDE, created by Prisma and based on GraphiQL. - Apollo docs

But what does that mean? It means that this is an environment where we can perform Queries, Mutations, or Subscriptions to our schema and interact with its data.

If you have worked with RESTful requests before this would be some kind of equivalent to Postman, just that here you do not have to download and configure anything, it just comes by default with Apollo!

awesome-chris-pratt

So let's try it!

  1. On the left panel write the greeting query we defined in our schema.
  2. Then press the β–Ά button that is in the middle.
  3. And Voila! On the right panel appears the data we defined in our resolver to return.

greeting-query-on-playground

Set up the Client

Now we have our server up and running let's focus on the client part. We will start creating a client.html file inside our client folder.

πŸ“ project
β”œβ”€β”€ πŸ“ client
|   └── πŸ“„ client.html
└── πŸ“ server
    └── πŸ“„ server.js
Enter fullscreen mode Exit fullscreen mode

The index.html file will have the basics of any HTML file and a loading header <h1>Loading...</h1> to show the user something while we request the data from the server.

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Hello World GraphQL Client</title>
  </head>

  <body>
    <h1>Loading...</h1>

    <script src="app.js"></script>
  </body>
</html>
Enter fullscreen mode Exit fullscreen mode

Fetching data from the server

First off, in the same client folder, we create an app.js file where we will write the client logic to fetch the data from the server.

πŸ“ project
β”œβ”€β”€ πŸ“ client
|   └── πŸ“„ client.html
|   └── πŸ“„ app.js
└── πŸ“ server
    └── πŸ“„ server.js
Enter fullscreen mode Exit fullscreen mode

Inside it, we set the server URL to which we will make the request.

const GRAPHQL_URL = 'http://localhost:9000/';
Enter fullscreen mode Exit fullscreen mode

Next, we define our async function fetchGreeting() to, fetch the greeting from the server. We will use the fetch API to perform the HTTP request which by default returns a promise to which we can subscribe and get the answer asynchronously.

async function fetchGreeting() {
  const response = await fetch(GRAPHQL_URL, {
    method: 'POST',
    headers: {
      'content-type': 'application/json',
    },
    body: JSON.stringify({
      query: `
        query {
          greeting
        }
      `,
    }),
  });

  const responseBody = await response.json();
  console.log(responseBody);
}
Enter fullscreen mode Exit fullscreen mode

A detail to take into account is that the method of the request is POST, which can confuse us if we are used to working with RESTful because this same request made in RESTful, where we just want to read information from the server, would be usually done with the method GET.

The thing is that with GraphQL we always make POST requests where we pass the query in the payload (body).

Finally, we just call our method fetchGreeting();

const GRAPHQL_URL = 'http://localhost:9000/';

async function fetchGreeting() {
  const response = await fetch(GRAPHQL_URL, {
    method: 'POST',
    headers: {
      'content-type': 'application/json',
    },
    body: JSON.stringify({
      query: `
        query {
          greeting
        }
      `,
    }),
  });

  const responseBody = await response.json();
  console.log(responseBody);
}

fetchGreeting();
Enter fullscreen mode Exit fullscreen mode

If you open the file in your browser and see the console on the developer tools you can see that we actually got the greeting data from the query πŸ™Œ!

fetching-data-from-server

Displaying the data

Now we have successfully got the data from the server lets update the loading title. The first thing we will do is destructure the response and return just the data from it.

Just replace this part of the code

const responseBody = await response.json();
console.log(responseBody);
Enter fullscreen mode Exit fullscreen mode

With this one

const { data } = await response.json();
return data;
Enter fullscreen mode Exit fullscreen mode

Then we will update the title with the greeting returned inside the data from the response

fetchGreeting().then(({ greeting }) => {
  const title = document.querySelector('h1');
  title.textContent = greeting;
});
Enter fullscreen mode Exit fullscreen mode

So our app.js file will end up having this look

const GRAPHQL_URL = 'http://localhost:9000/';

async function fetchGreeting() {
  const response = await fetch(GRAPHQL_URL, {
    method: 'POST',
    headers: {
      'content-type': 'application/json',
    },
    body: JSON.stringify({
      query: `
        query {
          greeting
        }
      `,
    }),
  });

  const { data } = await response.json();
  return data;
}

fetchGreeting().then(({ greeting }) => {
  const title = document.querySelector('h1');
  title.textContent = greeting;
});
Enter fullscreen mode Exit fullscreen mode

Our index.html will have the loading title updated with the data fetched from our server!πŸŽ‰

displaying-the-data

Conclusion

I hope you enjoyed the post and that this project has fulfilled the objective of showing how graphql works under the hood, at least in a very simple way. I know there are a lot of things that I have not explained or that I could have gone deeper but like any hello world project, it is intended for people who are beginners with it, so I wanted to keep it as simple as possible.

I'm looking forward to learning more about GraphQL and using it in future projects. If you've got any questions, suggestions, or feedback in general, don't hesitate to reach out on any of the social networks from my site or by mail.

Useful resources

Here is a collection of links and resources which have been useful for me to improve and learn more about GraphQL

Docs πŸ“š

Learn πŸ“

  • How to GraphQL - Free and open-source tutorials to learn all around GraphQL to go from zero to production.
  • GraphQL by Example - Great course where you learn GraphQL by writing full-stack JavaScript applications with Node.js, Express, Apollo Server, React, Apollo Client.
  • Introduction to GraphQL - A series of articles to learn about GraphQL, how it works, and how to use it.

Tools πŸ”§

IDEs πŸ’»

  • JS GraphQL - WebStorm and other IntelliJ-based IDEs plugin to support GraphQL language including tagged template literals in JavaScript and TypeScript.
  • GraphQL - GraphQL extension for VSCode adds syntax highlighting, validation, and language features like go to definition, hover information, and autocompletion for GraphQL projects. This extension also works with queries annotated with gql tag.
  • GraphQL for VSCode - VSCode GraphQL syntax highlighting, linting, auto-complete, and more!

Extras 🍍

  • GraphQL APIs - A list of public GraphQL APIs to test your skills or to build something with them.
  • GraphQL: The Documentary - A 30 min video that explores the story of why and how GraphQL appeared, and the impact it's having on big tech companies worldwide, including Facebook, Twitter, Airbnb, and Github.

Thank you for reading! You can read it too on my site along with others!

Top comments (1)

Collapse
 
baumannzone profile image
Jorge Baumann

Awesomic ✨