We’ve had great success with GraphQL in our React Native apps, so I wanted to try out GraphQL with Ember. Our team has many years of Ember experience, and I wanted to make sure:

We could continue to adopt GraphQL without blacklisting Ember from our available stack choices That the experience of using GraphQL in Ember didn’t feel like an afterthought.

With that in mind, how can we use GraphQL in Ember? By using ember-apollo-client. This is an Ember addon that wraps the Apollo library, which has emerged as the standard JavaScript client library for working with GraphQL.

Apollo handles fetching and mutating data, as well as caching records on the client using an internal datastore. Since this is exactly the same thing Ember Data does, we can replace Ember Data with ember-apollo-client.

Setup

Install and configure Apollo

ember install ember-apollo-client

Add the apollo configuration to config/environment.js . Set apiURL to the url of your GraphQL server.

Configuring Apollo

We’ll be using a pod structure in all the following examples, so if you’re using this article as a reference, make sure to set "usePods": true in your .ember-cli file.

Remove Ember Data

This is optional, but will reduce the final payload size of your application since we don’t need it.

npm uninstall ember-data

Querying Data

Just like with traditional Ember, there are two main places to query data.

The route’s model hook

hook In a component

ember-apollo-client supports both, but let’s examine the typical approach of loading data in a Route . Here are the steps:

Generate a new route ( ember g route games in this example) Add ember-apollo-client 's RouteQueryManager mixin Return a GraphQL query in the model hook Use it in the template

The ember-apollo-client README suggests placing all of our queries in a ggl folder, but we’ve found co-locating queries with the route or component that uses them helps give proper context. We use a similar structure in our React applications, and it works really well.

Here’s the folder structure we’ve landed on thus far, which fits very nicely into the pod structure of many Ember apps.

Example app folder structure

First up, here’s an example of a Route that fetches data using ember-apollo-client .

Example route

What does the RouteQueryManager mixin do? First, it makes Apollo available on the Route. If you use watchQuery , Apollo will act much like Ember Data — if another query or mutation modifies the data for this query (like changing an updatedAt field) it will immediately reflect the latest changes.

The mixin also handles unsubscribing from active queries when the route is destroyed. Without this, you’d need to unsubscribe manually when the route is torn down.

Next, let’s look at the query defined in queries.js .

An example query using ember-apollo-client

We’ve found it helpful to use multiple named exports inside queries.js — one for each query included in the file.

Finally, we use the data in the template. GraphQL returns a response with a top level data key. Under that, you have the name of the query/mutation you used. In our case, the query from queries.js is named allGames , so model.allGames will contain our game data.

An example template that uses a result from ember-apollo-client

Mutating Data

Let’s look at how to add a new game.

We could take the same approach as above and keep all the GraphQL logic in the Route, but to enable some easy data loading patterns in our form we’ll look at using it inside a component.

Just like the Route example above, we use the provided ComponentQueryManager which will unsubscribe any active Apollo queries when the component is torn down. Here’s a form component used to add a new game:

Note: if you want to use async/await like this, be sure to install the ember-maybe-import-regenerator addon or be sure you have includePolyfill: true in your Babel configuration.

Authorization

To add authorization to your GraphQL requests, you simply need to override the Apollo service and add a middleware function.

Example Auth Middleware

Final Thoughts

Having used GraphQL and Apollo extensively in React and React Native recently, I wanted to compare the experience in Ember.

The good news is we can leverage the power of GraphQL and:

avoid some of the complexity that can come from Ember Data

not have to create a second REST API

keep most of the Ember developer experience

Creating and querying records is a bit different than Ember Data, but still works well with the framework.