Why should you NOT use a GraphQL API Client

GraphQL Clients are not necessary for making GraphQL API Calls, and often complete overkill for the job at hand.

Woman in Red T-shirt Looking at Her Laptop

Imagine that your friend purchases a semi-truck because, “they run a lot of errands.” Any sane person would tell that friend that they’ve gone a little too far. Even the most modest, budget vehicle would likely do just fine for running their errands. No one needs a semi-truck to pick up hummus.

When it comes to software development, developers very often build semi-trucks when a sedan would get the job done. As a consequence, so much time then gets spent configuring, debugging, refactoring, and testing code that is complete overkill for the task that inspired it.

Take for example the following code snippet for setting up an Apollo GraphQL Client module:

import { HttpLink } from “apollo-link-http”;
import { onError } from “apollo-link-error”;
import { ApolloClient } from “apollo-client”;
import { setContext } from “apollo-link-context”;
import { InMemoryCache } from “apollo-cache-inmemory”;

/**
* A terminating link that fetches GraphQL results from
* a GraphQL endpoint over an http connection.
*
* docs: https://www.apollographql.com/docs/link/links/http/
*
* The 8base workspace endpoint goes here.
*/
const httpLink = new HttpLink({
uri: process.env.ENDPOINT
});

/**
* Error Link takes a function that is called in the event of an error.
* This function is called to do some custom logic when a GraphQL or
* network error happens.
*
* docs: https://www.apollographql.com/docs/link/links/error/
*/
const errorLink = onError(({ graphQLErrors, networkError }) => {
if (graphQLErrors) { graphQLErrors.map(console.log) }
if (networkError) console.log(`[Network error]: ${networkError}`);
});
/**
* Takes a function that returns either an object or a promise that
* returns an object to set the new context of a request.
*
* docs: https://www.apollographql.com/docs/link/links/context/
*
* Here we collect the authentication token from the auth module to
* add required bearer token to the headers.
*/
const authLink = setContext((_, { headers }) => ({
headers: {
authorization: `Bearer ${process.env.API_TOKEN}`,
…headers
}
}));
/**
* The ApolloClient class is the core API for Apollo, which we’re using
* to handle are GraphQL requests to the API.
*/
export default new ApolloClient({
/* Concatenate the many links */
link: errorLink.concat(authLink.concat(httpLink)),
/* Initialize the cache for helping performance */
cache: new InMemoryCache(),
connectToDevTools: true,
fetchPolicy: “no-cache”
});

5 required imports, 100’s of underlying dependencies, 30+ lines of code… Just like the semi-truck your friend bought to go run some errands, this API Client configuration file feels like way to much work to simply make some API calls, like:

query(name: String) {
food(name: $name) {
calories
}
}

At the end of the day, all GraphQL requests are HTTP POST requests. None of the fancy GraphQL clients are necessary to successfully make calls and get responses from a GraphQL API. So, why don’t we let it be as simple as making an POST request?

In recent projects, I’ve started using jQuery’s Ajax module to keep it simple. Doing so has made things quite…simple.

const query = `
query(name: String) {
food(name: $name) {
calories
}
}
`
const variables = { name: "Hummus" }
$.ajax({
url: process.env.ENDPOINT,
method: ‘post’,
dataType: ‘json’,
data: {
query,
variables
},
headers: {
Authorization: 'Bearer' + process.env.API_TOKEN
}
})
.then(responseHandler);

For a majority of applications developed that leverage GraphQL APIs, the data requirements can be summed up as simple queries and mutations being made to some backend API. There’s no need to over invest time and energy in configuring special API clients for performing not-so-special requests.

Of course, all tools — we hope — are created for a reason. The many libraries and toolkits created for working with GraphQL APIs have been established to assist in an extremely wide number of unique scenarios that developers have faced. However, if you don’t find yourself in one of those “unique scenarios”, there’s no need to spend hours solving problems you don’t have.

Posted