Introducing the Apollo GraphQL Platform for implementing the GraphQL Specification

Introducing the Apollo GraphQL Platform for implementing the GraphQL Specification

GraphQL is a query language and an execution run-time for APIs. It has a definite Type System, which makes it convenient to build schemas for various resources. GraphQL is declarative in nature and gives the client the power to ask exactly for what they need! It solves some of the problems of the traditional REST architecture like multiple end-points, over-fetching and under-fetching of resources, versioning, etc. Facebook built GraphQL in 2011 to solve the problems faced by its internal applications, and then open-sourced it in 2015. GraphQL has now gained the trust of startups to big companies like Intuit, Pinterest, Shopify, etc. You can read more on What is GraphQL and Why Facebook felt the need to build GraphQL?

GraphQL as a Specification

In the last few articles, we used graphql NPM module to define and execute GraphQL operations (queries and mutation). We also learned that GraphQL uses the concept of resolvers to fetch data for a respective field. One important thing to understand here is -- GraphQL is a Query language and Specification, and not an implementation of any technology per se, which means it is language-agnostic and can be implemented in any language of your choice. It is a Query language and defines the grammar for understanding its various constructs. For example, the specification clearly states the definition of Selection Sets as:

An operation selects the set of information it needs, and will receive exactly that information and nothing more, avoiding over‐fetching and under‐fetching data.

The Specification defines the selection set and its role in executing the queries. The implementation details may vary for different GraphQL clients.

But What is the GraphQL NPM module that we've been using?

The GraphQL NPM module is built by Facebook as a reference implementation in JavaScript. It is great to get up and running with the basic features in GraphQL. The graphql GitHub repository contains various sub-modules for implementing the core functionalities like:

ModuleUse
graphql/languageParse and operate on the GraphQL language
graphql/typeDefine GraphQL types and schema
graphql/validationThe Validation phase of fulfilling a GraphQL result
graphql/executionThe Execution phase of fulfilling a GraphQL request
graphql/errorCreating and formatting GraphQL errors
graphql/utilitiesCommon useful computations upon the GraphQL language and type objects
graphql/subscriptionSubscribe to data updates

The graphql module does the complex work of defining the types, implementing schema, parsing, validating and executing the queries. Some of the projects like Relay, Apollo GraphQL have used this core module and built a concrete GraphQL implementation in many different languages like JavaScript, Python, Java, etc.

What is Apollo GraphQL?

The Apollo GraphQL platform is an implementation of the GraphQL specification and uses graphql as one of the important dependencies. It comes bundled with Apollo Server, Apollo Client, and some excellent tooling modules to help write efficient and better code. The platform is convenient for developers to implement the complex GraphQL functionalities like Pagination, subscriptions, Caching, Authorization, and many more. We're going to look at each of these functionalities in detail soon! Let's first understand what Apollo Server is.

Apollo Server

Apollo Server can easily be integrated with most of the NodeJs HTTP server frameworks like Express, Koa, Hapi, Amazon Lambda, etc. The Apollo Server Express is the most popular implementation of the GraphQL server and we'll learn more about it in detail in this article.

In the last article, while building a Food Ordering System, we used expressGraphQL as middleware on the express server. The expressGraphQL middleware takes in the schema object.

To understand how Apollo Server fits in, we'll have to understand the working of middleware in detail. Let's do that right away:

A Middleware is a function that has access to the request and response objects and the next middleware function. It can intercept the incoming request and perform some computations on it to send the appropriate response. So, a middleware can:

  • Execute any code.
  • Make changes to the request and the response objects.
  • End the request-response cycle.
  • Call the next middleware function in the stack.

You can read more on using middleware in express here.

The expressGraphQL middleware should now make sense! It processes the incoming request on the graphql endpoint and accordingly executes the respective resolvers for the required fields.

Apollo Server works as middleware and has the power to perform computations on the request object and send back the appropriate response. Please note: The Apollo server can also be implemented as a stand-alone integration. The Apollo server uses the same concept of Schema and Resolvers that we've seen in the previous articles. Let's recap that quickly and write our minimal GraphQL server implementation using apollo-server.

Schemas & Resolvers in GraphQL

Schema is used for defining the structure of an entity. The GraphQL uses Schema Definition Language for implementing the schemas.

Resolvers are functions that are used for fetching the data from the data source for the various fields of the query.

Setting-up the Apollo Server

Let's install the dependencies first:

shell
npm install apollo-server graphql

We'll have to install graphql along with apollo-server because graphql is its peer dependency.

Let's write our simple Apollo server:

javascript
const { ApolloServer, gql } = require('apollo-server') const typeDefs = gql` type Query { userName: String } ` const resolvers = { Query: { userName: () => 'John' } } const server = new ApolloServer({ typeDefs, resolvers }) server.listen(3000, () => { console.log('Your Apollo Server is running on port 3000') })

Here we're using the stand-alone method to implement the Apollo Server.

The ApolloServer method and the gql tag are imported from the apollo-server module. The ApolloServer method takes in an object that contains the type definitions and resolvers. The gql tag is used for defining the schema into a multi-line template and it parses the template to generate an Abstract Syntax Tree.

The Query is a type and has one field userName of type String. The resolvers are defined in an object and each of the fields is resolved by using its respective function. Notice how the userName field is resolved to get a string John as an output. And the last statement should look familiar; we're running the server on port 3000.

Apollo Client

The apollo-client module is used on the client-side to build UI components that fetch data using GraphQL. It is one of the most popular modules to integrate GraphQL on the client-side and has around a million downloads on NPM. It can be integrated with most of the popular JavaScript libraries/frameworks like React, Angular, Vue, etc.

The companies like Airbnb, Netflix, The New York Times are using Apollo Client in production. The New York Times switched from Relay to Apollo Client because of its vibrant ecosystem, better server-side rendering, preloading/prefetching of certain queries, code-splitting at the component-level, persisted queries, etc. You can read more about their experience of switching to Apollo here.

The front-end applications are now getting build in modern libraries/frameworks like React, Angular, etc. These frameworks reduce a lot of boilerplate code of setting up the initial state and updating the DOM nodes, which was very difficult to achieve with the traditional libraries like JQuery.

The modern frameworks help in implementing complex functionality on the front-end. But to implement them, we're shipping a lot of JavaScript code over the wires, which in turn can worsen the performance of the application. The developers have to come up with clever ways to handle Caching, Data Normalization, etc.

State Management in React is hard and developers spend a lot of time in integrating the Redux boilerplates and many other features. Here's the slide from Peggy Rayzis presentation while she was explaining the cool new features in Apollo.

Image loading...alt text

Apollo Client does the heavy-lifting and makes Data Fetching, Caching, Authorization and other complicated features a breeze! Now you can easily integrate these features in your applications using Apollo Client.

We'll be using the React integration with Apollo Client for building the front-end of the Food Ordering System. If you've some experience in using React, you'd know that Data management in React is a big deal! You'll have to integrate Redux and dispatch appropriate actions to fetch data and show the loading or error states accordingly.

The Apollo Client is easy to set-up and all your state management logic is handled by the underlying mechanism.

Let's write a simple component that uses React Apollo Client to manage its data:

javascript
const getUser = () => { <Query query={user}> { ({ loading, error, data }) => { if (error) return <Error /> if (loading || !data) return <Loader /> return <User data={data.userDetails} /> }} </Query> }

The getUser is a stateless component and the Query component is imported from the Apollo client. It takes in one prop query. The next line is a function that accepts an object and we're using the ES6 Object destructing technique to get loading, error and data. The components Error, Loader, User are rendered based on these three values. You don't have to write reducers, action dispatchers to fetch data and store the state of the application. The Query component will do that out of the box! We'll get into the details of the client-side application in the next set of articles. Stay tuned!

Integrating the Apollo Platform

I hope, you're now convinced on using the Apollo Platform to implement the GraphQL specification! Let's start building our Food Ordering System in Apollo. If you're stuck anywhere in the code below, you can refer my GitHub respository to get to speed.

Installing the Dependencies

shell
npm install express apollo-server-express graphql --save

express: a Node.js web application framework that is used for building web and mobile applications. apollo-server-express: a module for integrating the express server with Apollo. graphql: an important peer dependency of apollo-server-express and is used for executing queries on the schema.

Let's also install nodemon as a dev-dependency. It automatically restarts the server when it detects a change in the application.

shell
npm install nodemon --save-dev

Let's add a script in package.json to run server.js on npm start command. Put this in your package.json file in the scripts object:

javascript
start: "nodemon server.js"

Setting-up the Server

Create a new file server.js in the root directory and add the below code:

javascript
const express = require('express') const { ApolloServer, gql } = require('apollo-server-express') const { typeDefs } = './schema' const { resolvers } = './resolvers' const app = express() const server = new ApolloServer({ typeDefs, resolvers }) server.applyMiddleware({ app }) app.listen({ port: 3000 }, () => { console.log('Your Apollo Server is running on port 3000') })

We're using the Middleware approach to integrate the ApolloServer with the express application. As we've seen earlier, ApolloServer accepts an object that contains the schema and resolvers. server.applyMiddleware({ app }) does the magic of connecting our express app with the apollo server!

The Apollo Server can intercept the incoming request object, perform computations on the query against its schema and send the appropriate response.

You'll get an error when you try to start the application because we've not added the schema and the resolvers file yet. Let's do that right away!

Defining Schemas

GraphQL uses Schema Definition Language to define types. It supports Scalar types like Int, String, Float, Boolean, ID and object types like query, mutation and subscription. If you are not familiar with the Type System in GraphQL, please refer this link.

We're building a Food Ordering System and its use-case is:

A user should be able to browse a list of restaurants. He can see the name, location, contact, email address and the menu for these restaurants. He can place an order for any item from the menu of his favorite restaurant. The customers’ order should be mapped accordingly with the restaurants.

You can read this article to get an overview of the project.

Create a schema.js file in the root directory. Let's start by defining the Restaurant type:

javascript
const { gql } = require('apollo-server-express') const typeDefs = gql` type Menu { id: ID, name: String, price: Float } type Restaurant { id: ID, name: String, email: String, location: String, menu: [Menu] } type Query { restaurants: Restaurant } ` module.exports = typeDefs

The type Query is the root type and it contains one field restaurants of type Restaurant. The structure of types is same as the previous article. There is one difference in the above schema and that of the previous implementation--we've not defined resolvers for any of the fields. We'll define resolvers for each field in a separate file resolvers.js.

Let's add two more types Customer and Order to complete our schema:

javascript
type Customer { id: Int, name: String, email: String, location: String } type Order { id: Int customerId: Int restaurantId: Int order: [String] }

Here's the entire code in schema.js file.

Defining Resolvers

The Query operation in GraphQL fetches data from one or more data sources while the mutation makes side-effects on the server.

Resolvers are used for instructing these operations to fetch/mutate data on the server. The resolvers object is a map of type fields and a resolve function is implemented for each of these fields. These function can either return an object or a promise. Once this promise is resolved, the children resolvers will take over and continue executing the operation.

Resolver Type Signature

Let's write a simple resolver to understand how fields are mapped with the main Query and what are the positional arguments of these functions:

javascript
const resolvers = { Query: { restaurants (parent, args, context, info) { /* Returning data after querying from the MongoDB collection */ } } }

The restaurants field gets resolved using the Query.restaurants function in the above map. This is a dummy resolver for now and does not return anything. We'll integrate MongoDB as our data source in the next article and then implement all of our resolvers.

The positional parameters of the resolve function are:

parent: As mentioned above, the resolver either returns data or a promise. The parent argument contains the data returned from the parent resolver.

args: We've already seen the use of args in this article. The args object is used for getting a specific set of data.

context: This Object is shared by all the resolvers in a particular query. It contains the information related to the request state like Authentication.

info: It is defined as GraphQLResolveInfo type and contains information about the execution state of the query like fieldName, fieldASTs, path and more.

Conclusion

This article is an overview of the Apollo GraphQL platform. We learned that:

  1. GraphQL is a specification and Facebook built graphql module as a reference implementation in JavaScript. The Apollo GraphQL platform is a complete implementation of the GraphQL and is extensively used by the community.
  2. The Apollo Server can be integrated with the express framework as middleware and it takes in the schema and the resolvers. It uses the GraphQL Schema Definition Language to define types.
  3. The Apollo Client is one of the popular ways to integrate GraphQL on the client-side. It solves various tough problems like Data Fetching, State Management, Caching on the client-side. It helps to eliminate a lot of boilerplate code in Redux which was used for handling the state and dispatching actions.
  4. We learned how to write an Apollo server using the apollo-server-express module. We also implemented the type definitions of Entities that are used in the Food Ordering System.
  5. The Query component on the client-side makes it convenient to handle state in React.

In the next article, we'll integrate MongoDB data source with our Apollo Server. We'll also implement the resolvers for various fields in the Food Ordering project and fetch data from the collections in MongoDB.

Next in series: How to Connect MongoDB to a GraphQL Server?

Read similar articles