GraphQL

Apollo Server – Introduction


Subscribe On YouTubeCode

Apollo Server is a library that helps you connect a GraphQL schema to an HTTP server in Node.js. It’s possible to use Apollo Server with all popular HTTP servers like Express, Connect, Hapi, Koa, Restify, and Lambda. In this tutorial you’ll learn how to set up Apollo Server with Node.js and Express. Let’s get started.

The Apollo Server project’s website can be found https://www.apollographql.com/servers:

Setting Up The Project

To create a new Node.js project let’s first create a new empty project directory:

$ mkdir node-apollo

Change into the new directory

$ cd node-apollo

and then initialize the a new package.json file by using the npm command:

$ npm init -y

Setting Up Babel

In order to be able to use ES6 features in our Node.js code we need to set up the Babel compiler for our project. Enabling Babel is very easy, first you need to install the packages babel-cli and babel-preset-env via NPM:

$ npm install --save-dev babel-cli babel-preset-env

Once installed you need to add a .babelrc file to the project and add the content:

{
  "presets": ["env"]
}

Now we’re ready to use the Babel compiler for the project.

Installing babel-watch

Starting the Babel compiler manually after every code change would be inconvenient. By using babel-watch we can automate this task and in addition making sure that the Node.js web server process is restarted as well. Let’s add babel-watch as a dependency to our project:

$ npm install babel-watch --save-dev

Then use babel-watch in your package.json file in scripts section like this:

  "scripts": {
    "dev": "babel-watch server.js"
  }

Later on, when we’ve implemented the server in file server.js this will enable us to start the server by using the following command:

$ npm run dev

This command will then execute babel-watch which starts the Node.js server and makes sure that the Babel tarnspiler is running in watch mode as well. Everytime the implementation is changed the compilation is done automatically and the Node.js server is restarted again, so that everything is updated without needed to perform manual steps.

Installing Express And Apollo Server

Because we’d like to use the Express framework for implementing the Node.js GraphQL server we’re installing the corresponding package first:

$ npm install express

Furthermore we need to make sure that the dependencies graphql, graphql-tools and apollo-server-express are installed:

npm install graphql graphql-tools apollo-server-express

Implementing The Server

Implementing A Basics Node.js/Express Server

To be able to implement the server we first need to add a new file server.js to our project:

$ touch server.js

Next, you can open up this file in your favorite text editor and add the following code:

import express from 'express';

const app = express();
app.get('/', (req, res) => res.send('Hello World!'));
app.listen(4000, () => console.log(`Express server running on port 4000`));

Start the server process by executing

$ npm run dev

You then should be able to see the following output on the command line:

If you now access URL http://localhost:4000 in the browser you’ll get the following response from the Node.js/Express server.

Adding A GraphQL Endpoint

Now that our basic Node.js/Express server is running we can add a GraphQL endpoint by using Apollo Server. Therefore we need to change the code inside file server.js to the following:

import express from 'express';
import bodyParser from 'body-parser';
import { graphqlExpress } from 'apollo-server-express';

const app = express();

app.use('/graphql', bodyParser.json(), graphqlExpress({}));

app.listen(4000, () => console.log(`Express server running on port 4000`));

First we need to make sure that graphqlExpress is imported from the apollo-server-express library. Next we’re able to attach the graphqlExpress middleware to the /graphql endpoint by calling app.use. Furthermore we’re making use of the bodyParser.json middleware as well.

The call of graphqlExpress is requiring a configuration object as an parameter. Currently this object is empty. In the following steps this configuration object will be used to supply the GraphQL middleware with schema and resolvers.

Adding An Endpoint For GraphiQL

Let’s add a second endpoint for GraphiQL to the Express server next. GraphiQL is a graphical interactive in-browser GraphQL IDE. By using this tool you can directly write your queries in the browser.

import express from 'express';
import bodyParser from 'body-parser';
import { graphqlExpress, graphiqlExpress } from 'apollo-server-express';

const app = express();

app.use('/graphiql', graphiqlExpress({
    endpointURL: '/graphql'
}));

app.use('/graphql', bodyParser.json(), graphqlExpress({}));

app.listen(4000, () => console.log(`Express server running on port 4000`));

In order to add the GraphiQL endpoint we need to import the graphiqlExpress middleware from the apollo-server-express library. The respective endpoint is added to the server by calling app.use once again:

app.use('/graphiql', graphiqlExpress({
    endpointURL: '/graphql'
}));

The graphiqlExpress middleware is attached to the /gaphiql endpoint. The configuration object which is passed to graphiqlExpress is containing one property: endpointURL. The value of this property needs to be set to our GraphQL endpoint which should be used together with GraphiQL.

If you now try to access URL http://localhost:4000/graphiql in the browser you should be able to see the GraphiQL user interface:


On the right side you’ll receive an error message, stating that a GraphQL schema could not be found. Adding a GraphQL schema to the server is the next step.

Adding A Schema

To configure the GraphQL server properly we first need to add a schema. To do so let’s create a new file in the project directory:

$ touch schema.js

Insert the following schema definition inside that file:

const typeDefs = [`
    type Course {
        id: Int
        title: String
        author: String
        description: String
        topic: String
        url: String
    }
    type Query {
        allCourses: [Course]
        course(id: Int!): Course
    }
`];

This schema consists of one custom type Course and two query types: allCourses and course. The custom Course type consists of six properties in total. The queries which are defined can be used to either retrieve all courses available (via query allCourses or retrieve just one course by ID (via query course).

Adding Resolvers

Next thing we need to add are the corresponding resolvers. Resolvers are functions which are assigned to a query or mutation and contain the logic which is needed to retrieve and return the relevant data. Let’s add another file to the project:

$ touch resolvers.js

Next insert the following code in the newly created file:

var coursesData = [
    {
        id: 1,
        title: 'The Complete Node.js Developer Course',
        author: 'Andrew Mead, Rob Percival',
        description: 'Learn Node.js by building real-world applications with Node, Express, MongoDB, Mocha, and more!',
        topic: 'Node.js',
        url: 'https://codingthesmartway.com/courses/nodejs/'
    },
    {
        id: 2,
        title: 'Node.js, Express & MongoDB Dev to Deployment',
        author: 'Brad Traversy',
        description: 'Learn by example building & deploying real-world Node.js applications from absolute scratch',
        topic: 'Node.js',
        url: 'https://codingthesmartway.com/courses/nodejs-express-mongodb/'
    },
    {
        id: 3,
        title: 'JavaScript: Understanding The Weird Parts',
        author: 'Anthony Alicea',
        description: 'An advanced JavaScript course for everyone! Scope, closures, prototypes, this, build your own framework, and more.',
        topic: 'JavaScript',
        url: 'https://codingthesmartway.com/courses/understand-javascript/'
    }
];

const resolvers = {
    Query: {
        allCourses: () => {
            return coursesData;
        },
        course: (root, {id}) => {
            return coursesData.filter(course => {
                return course.id === id;
            })[0];
        }
    }
}

export default resolvers;

First of all we’re defining an array coursesData with three sample records which will be used as the data store.

Furthermore the code contains the resolvers object which contains the assignment of two arrow functions to queries. The function which is assigned to the allCourses query is just returning the coursesData array. The function which is assigned to the course query is using the filter method of the coursesData array to retrieve the course with the requested ID and then return this course.

Finally the resolvers object is exported so that we can import it again in file schema.js:

import { makeExecutableSchema } from 'graphql-tools';
import resolvers from './resolvers';

const typeDefs = [`
    ...
`];

const schema = makeExecutableSchema({
    typeDefs,
    resolvers
});

export default schema;

Now the schema definition (typeDefs) and the resolvers object are both available so that the makeExecutableSchema function can be called to make the schema usable for setting up the GraphQL server endpoint with Apollo Server.

Therefore makeExecutableSchema is imported from the graphql-tools library first. The function is called with one parameter: an object containing typeDefs and resolvers. The resulting executable schema is stored in schema and exported, so that we can use it in server.js by using the following import statement in this file:

import schema from './schema';

Now we’re able to pass the schema to the configuration object which is passed to the call of the graphqlExpress middleware:

app.use('/graphql', bodyParser.json(), graphqlExpress({schema}));

By attaching the schema to the endpoint we’ve now completed the server configuration. Let’s test this endpoint by using GraphiQL in the next step.

Executing Queries

Retrieving All Courses

Let’s open GraphiQL in the browser by accessing URL http://localhost:4000/graphiql and entering the following GraphQL query to retrieve the complete list of courses:

{
  allCourses{
    id
    title
    author
    description
    topic
    url
  }
}

The result should correspond to what you can see in the following screenshot:

Retrieving A Single Course By ID

Next, let’s use our second query type and select and single course by it’s ID:

{
  course(id: 1){
    id
    title
    author
    description
    topic
    url
  }
}

As a result you should be able to see the course with ID 1 in the output area:

 

ONLINE COURSE: GraphQL with React: The Complete Developers Guide

Check out the great GraphQL with React: The Complete Developers Guide course with thousands of students already enrolled:

GraphQL with React: The Complete Developers Guide

  • Learn and master GraphQL by building real web apps with React and Node
  • Build amazing single page applications with React JS and GraphQL
  • Realize the power of building flexible data schemas
  • Master fundamental concepts behind structuring GraphQL servers
  • Be the engineer who explains how GraphQL works to everyone else, because you know the fundamentals so well

Go To Course

ONLINE COURSE: Node.js, Express & MongoDB Dev to Deployment

Check out the great Node.js, Express & MongoDB Dev to Deployment course with thousands of students already enrolled:

Node.js, Express & MongoDB Dev to Deployment

  • Learn by example building & deploying real-world Node.js applications from absolute scratch
  • Build high quality applications built with Node, Express and MongoDB
  • Create data models with Mongoose ODM
  • Learn ES6 concepts like arrow functions, template strings & promises
  • Implement authentication including local & Google OAuth strategies
  • Prepare & deploy apps to production with Heroku

Go To Course


Using and writing about best practices and latest technologies in web design & development is my passion.