Getting started with GraphQL and Node.js

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

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 typesSong and Author like this

type Song {
  title: String
  author: Author
}

type Author {
  name: String
  song: [Song]
}

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]
}

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
}

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

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 typeDefsconstant 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
}
`;

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!👋',
  },
};

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 });

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}`));

We can also destructure the ServerInfo url when logging it.

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

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}`));

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/

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 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!

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.

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

The index.html file will have the basics of any HTML file and a loading header 

Loading...

 to show the user something while we request the data from the server.



  
    
    
    Hello World GraphQL Client
  

  
    

Loading...

http://app.js

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

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

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

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);
}

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();

If you open the file in your browser and see the console on the developer toolsyou can see that we actually got the greeting data from the query 🙌!

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 datafrom it.

Just replace this part of the code

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

With this one

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

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;
});

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;
});

Our index.html will have the loading title updated with the data fetched from our server!🎉

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.

from Tumblr https://generouspiratequeen.tumblr.com/post/635845738454188032

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s