In this article, we walk through the process of constructing a GraphQL API in Node.js using the Apollo Server library. We’ll learn how to define schemas, implement resolvers and leverage the Apollo Sandbox interface for running GraphQL operations on the web.
GraphQL is a query language for making requests to APIs. With GraphQL, the client tells the server exactly what it needs and the server responds with the data that has been requested. To get a better understanding of some of the things that make GraphQL special, be sure to read the earlier article: GraphQL vs. REST—Which is Better for API Design?.
There are two sides to using GraphQL: as an author of a client or frontend web application, and as an author of a GraphQL server. In this chapter, we’re going to focus entirely on the latter—by going through a simple exercise on how we can create a GraphQL server API.
It’s important to always keep in mind that GraphQL is a specification, not a direct implementation. This means that a GraphQL API can be created in many different programming languages— Ruby, Java, Python and so on. We’ll focus on creating a GraphQL API with JavaScript and we’ll use the Apollo Server library to help us achieve this.
We’ll be creating a GraphQL API with Node.js. We assume you have Node and the
npm
package manager already installed.
We’ll begin with an empty folder called graphql-api/
.
graphql-api/
In the graphql-api/
folder, we’ll create a package.json
file. The package.json
file is where one can provide metadata about a Node application, list
the packages the app depends on, and create scripts to run the app.
graphql-api/
package.json
In the package.json
file, we’ll introduce name
and version
fields to describe the project we intend to create. We’ll name our project “graphql-api” and specify the version as “0.1.0”.
{
"name": "graphql-api",
"version": "0.1.0"
}
We’ll now install the @apollo/server
package and the graphql
JavaScript library in our project.
@apollo/server
will be used to create our GraphQL API and help instantiate a server.graphql
is a peer dependency needed by the Apollo Server package.In our terminal, we’ll install these new packages as application dependencies.
graphql-api $: npm install @apollo/server graphql
We’ll create an index.js
file in our project directory which will be the location where we create our GraphQL API.
graphql-api/
index.js
package.json
In the index.js
file, we’ll prepare some mock data that we’ll use to query from our GraphQL API. Our mock data will be an array of listings where each listing item will have the fields—id
,
title
and city
.
const listings = [
{ id: "001", title: "Large ensuite condo", city: "Toronto" },
{ id: "002", title: "Beverly Hills Mansion", city: "Los Angeles" },
{ id: "003", title: "Small chic bedroom", city: "Dubai" },
];
The first thing we’ll do to create our GraphQL API is prepare the GraphQL schema. A GraphQL schema describes all the possible data that can be requested. We can think of a schema as the blueprint of a GraphQL API. We’ll create the schema with the GraphQL Schema Language which is a simple and language-agnostic syntax.
The GraphQL schema is where we specify the types of fields we’ll want to be queried from the API. We’ll construct a schema where we’ll be able to query a listings
field which will return a list
of listings from the mock data array we’ve prepared.
With the schema we have in mind prepared, our index.js
file will now look like the following:
const listings = [
{ id: "001", title: "Large ensuite condo", city: "Toronto" },
{ id: "002", title: "Beverly Hills Mansion", city: "Los Angeles" },
{ id: "003", title: "Small chic bedroom", city: "Dubai" },
];
const typeDefs = `#graphql
type Listing {
id: String!
title: String!
city: String!
}
type Query {
listings: [Listing!]!
}
`;
What’s happening here?
typeDefs
.Listing
object type that represents the shape of a single listing object. The Listing
object is to have three fields of which all are to be strings—id
, title
and city
.
Query
object type in our schema which represents the root-level fields that can be queried from the client. We’ve stated listings
to be a field that can be
queried and when resolved will return a list of Listing
object types.Our schema simply represents the shape of data that can be queried. To define how the fields in the schema get processed, we’ll create our GraphQL resolvers. Resolvers in a GraphQL API are functions responsible for resolving a GraphQL operation to data.
We’ll specify a resolvers
map to dictate how the listings
field is to resolve. We’ll have the listings
field simply return the mock listings
array we’ve created.
const resolvers = {
Query: {
listings: () => listings,
},
};
With our schema, resolvers and mock data defined, we can now create our Apollo Server instance. To do so, we’ll import and use the ApolloServer
constructor function from the @apollo/server
library.
The ApolloServer
constructor takes an options
object that requires us to pass values for a typeDefs
field (i.e., the GraphQL schema) and a resolvers
field (i.e., the map of functions that resolve to concrete data).
We’ll run the ApolloServer
constructor, pass the typeDefs
and resolvers
constant values we’ve created, and assign the result to a constant called
the server
.
const { ApolloServer } = require("@apollo/server");
// ...
const server = new ApolloServer({ typeDefs, resolvers });
With the Apollo server
instance now available to us, we can start our web server by running the startStandaloneServer()
function available to us from the @apollo/server/standalone
package.
The startStandaloneServer()
function is an asynchronous function that when resolved receives the url
of the running server. We’ll log a message to the console with this url
value.
Our index.js
file in its entirety will now look like the following.
import { ApolloServer } from "@apollo/server";
import { startStandaloneServer } from "@apollo/server/standalone";
const listings = [
{ id: "001", title: "Large ensuite condo", city: "Toronto" },
{ id: "002", title: "Beverly Hills Mansion", city: "Los Angeles" },
{ id: "003", title: "Small chic bedroom", city: "Dubai" },
];
const typeDefs = `#graphql
type Listing {
id: String!
title: String!
city: String!
}
type Query {
listings: [Listing!]!
}
`;
const resolvers = {
Query: {
listings: () => listings,
},
};
const server = new ApolloServer({ typeDefs, resolvers });
startStandaloneServer(server).then(({ url }) => {
console.log(`Server is running at ${url}`);
});
In our terminal, we’ll run node index.js
within the graphql-api/
folder to run the contents of the index.js
file and start our web server.
graphql-api $: node index.js
With the server running appropriately, we should see the expected message to the console.
Our GraphQL API is now running on http://localhost:4000
!
If we navigate to http://localhost:4000
in our browser, we’ll launch the Apollo Sandbox.
Apollo Sandbox is a web-based tool for running GraphQL operations.
With the sandbox, we can query for the listings field and specify we want the id
, title
and city
for each listing object to be returned.
query {
listings {
id
title
city
}
}
When we run the query, we’ll get all the listing objects from our mock data with the fields we’ve specified.
What if we only wanted to retrieve the id
of each listing? We’ll have our query reflect this by only querying the id
field within the listings
parent field.
query {
listings {
id
}
}
And that’s it! We’ve created a GraphQL API in a matter of minutes with which we’re able to have the client dictate what data it wants from the server.
Test the above in this Codesandbox link.
In this tutorial, we delved into the fundamentals of creating a GraphQL API using Apollo Server. With Apollo Server, we were able to define our schema, implement resolvers and finally run our GraphQL server—enabling us to query our mock listings through the Apollo Sandbox UI.
Stay tuned for our follow-up article that takes a look into how we can query a GraphQL API in a React application!
Hassan is a senior frontend engineer and has helped build large production applications at-scale at organizations like Doordash, Instacart and Shopify. Hassan is also a published author and course instructor where he’s helped thousands of students learn in-depth frontend engineering skills like React, Vue, TypeScript, and GraphQL.