Using GraphQL in Web 🚀

One of the first things one comes across when dealing with GraphQL for web applications is the Apollo GraphQL library by Meteor Development Group Inc. The Apollo Client provides an easy-to-use client for a GraphQL endpoint and is available for most platforms, including Angular, iOS and Android.

In addition to create the queries we use the graphql-tag library.

The Configuration

To work with our api it is necessary to configure two things. First you need to configure the library to use the correct graphql endpoint, called client. I'd recommend configuring it so it can use multiple endpoints. The main endpoint should be named default.

For this you need to inject the Apollo and HttpLink provider and call the .create() method on it for each client. You also need InMemoryCache of the apollo-cache-inmemory package. In the following code options.clients is a object containg the endpoints name as key and its url as value. middleware is a middleware which sets authorization headers and handles errors describe in the authorization and in then Handling Errors section.

const clientKeys = _.keys(options.clients);
_.each(clientKeys, k => {
  apollo.create({
    link: concat(middleware, httpLink.create({uri:options.clients[k]})),
    cache: new InMemoryCache(memoryOptions)
  }, k);
});

The second thing you need to configure is the fragmentMatcher in the memoryOptions of the InMemoryCache to use graphql fragments. For this you need the IntrospectionFragmentMatcher. Therefore you need to query the GraphlQL schema with the following query and save it to introspectionQueryResultData:

{
  __schema {
    types {
      name
      kind
      possibleTypes {
        name
      }
    }
  }
}

After that you build the options for the InMemoryCache:

const memoryOptions = {
  fragmentMatcher: new IntrospectionFragmentMatcher({
    introspectionQueryResultData
  })
}

The memoryOptions are then used in the client configuration above.

The Queries

Building queries like you are familiar with from the GraphiQL client, we use the graphql tag like so

const userQuery = gql`
  query user($userId: String!) {
    user(userId:$userId) {      
      id
      name
    }
  }`;

This query requires the input of a userId to get the users id and name field.

The Service

Using the apollo Angular client you can now, after it is correctly configured, send GraphlQL queries and mutations with it. The result will be, like the result of a http request, a Observable. You need to inject the Apollo provider for this.

this.apollo.use(use).query({
  query: userQuery,
  variables: { userId: 1 }
});

use is the name of the client, if now value is passed here, the default client will be used. variables is an object containing all variables that should be passed to the query.

Response

This is an example response to a GraphQL user query.

{
  "data": {
    "userQuery": {
      "id": 1,
      "name": "Yoli"
    }
  }
}

Handling Errors

You can define custom error handling by using the onError link from the apollo-link-error and adding it to the middleware. In our case we just return an error with Observable.throw and let the specific requests observable handle the error itself:

const errorLink = onError(({ graphQLErrors, operation, networkError }) => {
  return Observable.throw(graphQLErrors || networkError);
});
const middleware = errorLink.concat(appHeaderLink);

Now you use the middleware as described in the configuration section above.

Localization

Some queries require an input which describes the current localization (e.g. "de" for Germany). We'd recommend using a localiaztion library like angular-l10n for this.