DEV Community

Chigozie Oduah
Chigozie Oduah

Posted on

Build a GraphQl server with NodeJS and Express

Introduction

In this article, you will learn how to build GraphQl servers using Express in NodeJS. GraphQl is a quick, and easy way to build backends that communicate effectively with frontends, and control resources.

Prerequisites

This article only covers the basics of GraphQL, which means you have to have knowledge of NodeJS and ExpressJS to fully understand the contents.

What is GraphQL?

GraphQL is an open-source data query language, and runtime for creating APIs and responding to queries with existing data. GraphQL makes it very simple to create backend APIs. To retrieve all the data an app needs from the server, it only needs a single query to a GraphQL API instead of sending multiple requests to more than one endpoint.

GraphQL APIs can be created in common programming languages, like Python, Java, JavaScript, Scala, Ruby, and a lot more. Any type of application can interact with a GraphQL API, as long as it can make requests to an endpoint.

Benefits of GraphQL

GraphQl APIs have numerous benefits over RESTful APIs. They are:

  • Getting the exact data needed: In GraphQL, we can get exactly what we need from the server using a query. Unlike REST APIs that give you all the data that can be gotten from an endpoint, which makes communication between server and clients very slow and inefficient.
  • Retrieve large amounts of data with a single query: With GraphQL APIs, we can get all the data that our app needs in a single request, unlike most REST APIs, which require loading from multiple endpoints.
  • Rich Type system: GraphQL APIs don’t use endpoints for organization. Instead, they are organized in types and fields, which helps to give helpful messages if the server encounters any error. GraphQL uses a single endpoint, usually named “/graphql”, that a client uses to communicate with the backend.
  • Uniform API design: GraphQL APIs have a uniform design across multiple programming languages. GraphQL APIs don’t need much modifications to be ported from one programming to another. In GraphQL, we use a schema to describe what our API can do. Designing objects that fit the schema is easy to do in GraphQL.

Building a RESTful API with Express

Before building our API using GraphQL, we will build its REST version The API we create will have two endpoints:

  • /say-message, which responds with a message from the server.
  • /change-message, which changes the message on the server.

To create this API, we perform the following steps in our already initialized project folder:

  • Install the express package using any of the following commands:
Package Manager Command
Yarn npm install express
Npm yarn add express
  • Create an index.js file, and write the following into it:
// import the express library
const express = require('express');


// create the express application
const app = express();


// register the "express.text()" middleware to parse incoming text requests
app.use(express.text());





// This variable stores a string that the endpoints below manipulate
let text = "Hello, World";


// create an endpoint to get the `text` string
app.get("/say-message", (req, res) => {


  // send a response with text
  res.send(text);

});

// create an endpoint to change the `text` string
app.post("/change-message", (req, res) => {


  // change the text of "text" variable to the one sent in the request
  text = req.body;


  // send a response with text
  res.send(text);

});





// Run the server on localhost port 8080
app.listen(8080, () => console.log("Server running...."));
Enter fullscreen mode Exit fullscreen mode

If we run the following requests in our frontend, we get the following responses from the server:

Action Frontend request Response
Getting the message from the server fetch("http://localhost:8080")

.then(req => req.text())

.then(message => console.log(message));

Hello, World!
Changing the message on the server // change the message

fetch("http://localhost:8080", {

'method': 'POST',

'headers': {

'Content-type': 'application/text',

},

'body': 'Humans'

})

.then(req => req.text())

.then(message => console.log(message));

// get the message

fetch("http://localhost:8080")

.then(req => req.text())

.then(message => console.log(message));

Hello, Humans!

Building an API with GraphQL and Express

In this section, we will build the GraphQL version of the API we built above. To build our API, we have to install the following libraries:

  • graphql, to use core graphql features in our code.
  • express, to build the graphql endpoint.
  • express-graphql, to use graphql in an express application.

To install the libraries above, we use any of the following commands:

Package Manager Command
Yarn yarn add express graphql express-graphql
Npm npm install express graphql express-graphql

Once we have the libraries installed, we create an index.js file and copy the following into it:

const express = require('express');
const { graphqlHTTP } = require('express-graphql');
const { buildSchema } = require('graphql');

let schema = buildSchema(`
  type Query {
    message: String
  }

  type Mutation {
    changeMessage(message: String): Boolean
  }
`)

class Root {
  text = "Hello, World!";

  message() {
    return this.text;
  }

  changeMessage({ message }) {
    this.text = message;
    return true;
  }
}

const app = express();

app.use('/graphql', graphqlHTTP({
  graphiql: true,
  schema: schema,
  rootValue: new Root(),
}))

app.listen(8080, () => {
  console.log("Server running...");
})
Enter fullscreen mode Exit fullscreen mode

The following is an explanation of the program above:

const express = require('express');
const { graphqlHTTP } = require('express-graphql');
const { buildSchema } = require('graphql');

Enter fullscreen mode Exit fullscreen mode
  • In the snippet above, we imported the following:
    • express, a constructor function for creating backend applications
    • graphqlHttp, an express middleware function for using graphql in the application
    • buildSchema, a function from graphql that creates a schema using the schema language
let schema = buildSchema(`
  type Query {
    message: String
  }

  type Mutation {
    changeMessage(message: String): Boolean
  }
`)

Enter fullscreen mode Exit fullscreen mode
  • In the snippet above, we built our schema using the graphql schema language.In GraphQL, a schema is a description of the requests that a client can make to the backend. The Schema defines all of the queries and mutations that clients can make. Queries return data from the server, while mutation changes data on the server.
class Root {
  text = "Hello, World!";

  message() {
    return this.text;
  }

  changeMessage({ message }) {
    this.text = message;
    return true;
  }
}

Enter fullscreen mode Exit fullscreen mode
  • In the snippet above, we create a class that defines the methods for the schema. Just having our schema is not enough, we also need to implement it. We use a class to create the interface between our backend and GraphQL. This class defines methods that respond to a specific request made to the api.
const app = express();

app.use('/graphql', graphqlHTTP({
  graphiql: true,
  schema: schema,
  rootValue: new Root(),
}))

Enter fullscreen mode Exit fullscreen mode
  • In the snippet above, we create our application by calling the express factory function. Then we register the graphqlHTTP middleware function to the /graphql endpoint. In the graphqlHTTP middleware function, we pass an object that contains the following:
    • graphiql, to enable a GUI, which looks like the image below, for testing graphql queries.
    • schema, to register the schema that we created.
    • rootValue, to register the root object for graphql.

alt_text

In the interface above, if we make the following queries in the order on the table below, we will get the below responses:

Query Response
query {

message

}

{

"data": {

"message": "Hello, World!"

}

}

mutation {

changeMessage(message: "Humans")

}

{

"data": {

"changeMessage": true

}

}

query {

message

}

{

"data": {

"message": "Hello, Humans!"

}

}

In GraphQL, a request can either be a query, or a mutation, but not both, which means you cannot send a request like the below:

mutation {
  changeMessage(message: "Humans")
}
query {
  message
}
Enter fullscreen mode Exit fullscreen mode

The table below represents the schemas, and queries and classes for different types of ways we can create and interact with GraphQL applications.

Type Request body Schema Basic class
Single Query query {

message

}

type Query {

message: String

}

class Root {

message() {

}

}

Multi Query query {

message

number

}

type Query {

message: String

number: Int

}

class Root {

message() {

}

number() {

}

}

Nested Multi Query query {

message

extraData {

number

}

}

type Query {

message: String

extraData: ExtraData

}

type ExtraData {

number: Int

}

class Root {

message() {

}

extraData() {

return new ExtraData();

}

}

class ExtraData {

number() {

}

}

Single Query With Arguments query {

message(text: "Hi")

}

type Query {

message(text: String): String

}

class Root {

message({ text }) {

}

}

Single Mutation mutation {

message(text: "Hi")

}

type Mutation{

message(text: String): String

}

class Root {

message({ text }) {

}

}

Multi Mutation mutation {

message(text: "Hi")

age(number: 18)

}

type Mutation {

message(text: String): String

age(number: Int): Int

}

class Root {

message({ text }) {

}

age({ number }) {

}

}

Nested Multi Mutation mutation {

message(text: "Hi")

properties {

age(number: 18)

}

}

type Mutation {

message(text: String): String

properties: Properties

}

type Properties {

age(number: Int): Int

}

class Root {

message({ text }) {

}

properties() {

return new Properties();

}

}

class Properties{

age({ number }) {

}

}

Conclusion

In this article, we covered the basics of creating APIs with Express, the GraphQL framework and creating GraphQL based APIs. GraphQL is a quick and easy way to join both frontend and backend applications together. I hope this article helps to understand creating APIs with GraphQL better. To further your knowledge on the subjects you can use the following links:

Top comments (0)