Working with Vue and Apollo GraphQL
What is GraphQL
GraphQL is an alternative way to traditional RESTFul API for data fetching. It has been trending in the industry that many companies start using it as part of their tech stacks, including Article. The benefit it provides includes specifying the response you want to fetch, code being the documentation, and allow you to easily connect different services to provide the data for frontend. You can read more about it and our initiative to move to GraphQL from my article Moving to GraphQL.
Vue and Apollo GraphQL
In order to talk to a GraphQL backend, usually we would use a GraphQL client that is designed to do such things. Writing out the query by hand into a POST or GET request is not something that developers would be happy to do so so these clients are here to make that easier. There are many clients available and I choose to use Apollo for its ecosystem and the community.
For the purpose of this blog post, I assume the GraphQL query looks something like:
query Product($id: ID!) {
product(id: $id) {
title
skuNo
price
}
}
The final stable release of Vue 3 is imminent so the code examples that will be used will be in Vue 3. However the syntax will mostly be the same if you are already using Composition API in Vue 2. This article also doesn't cover using the popular library vue-apollo or @vue/apollo-composable as they aren't working with Vue 3 officially yet. So I will use the Apollo client directly and that is actually how we do thing in our team at Article. I personally like this approach as it gives better understanding on how the underlying modules work and we can understand better which module is responsible for what when we introduce new layers.
Show Me the Code
Let's first install the Apollo Client module by running
# if you are using yarn
yarn add @apollo/client
#if you are using npm
npm install @apollo/client
I first create a JavaScript file that is responsible for creating an Apollo client. Every time you need to send a GraphQL query in your component you would use this createApolloClient
method to get an Apollo client instance. If you keep creating a new Apollo client instance you would lose the query caches you have previously accumulated.
import { ApolloClient, HttpLink } from '@apollo/client/core';
import { InMemoryCache } from '@apollo/client/cache';
let apolloClient = null;
export function createApolloClient() {
if (apolloClient) {
return apolloClient;
}
return apolloClient = new ApolloClient({
link: new HttpLink({
uri: "http://localhost:4001/graphql",
}),
cache: new InMemoryCache(),
});
}
The link
property basically tells the Apollo client where it should send the queries or mutations to. You can also incorporate custom headers as part of the query, such as the authorization token, by utilizing setContext
method.
import { ref } from "vue";
import { createApolloClient } from '../apollo.js';
import { gql } from '@apollo/client/core';
export default {
name: "PageQuery",
setup() {
const apolloClient = createApolloClient();
const result = ref(null);
async function query() {
try {
const queryResult = await apolloClient.query({
query: gql`
query product($productId: ID!) {
product(id: $productId) {
title
skuNo
}
}
`,
variables: {
productId: 123,
}
});
result.value = queryResult.data;
} catch(error) {
console.error(error);
}
}
return {
result,
query,
};
}
}
</script>
Composition API is an alternative to the current Options API in Vue that aims to separate your logic from your UI and also let us write our code in more functional fashion. My trip to Vue Toronto conference should help you understand more. The ref
I use here is part of Composition API that basically makes it reactive. gql
allows us to write the GraphQL query in the same way that you would write in your Playground. And we import the createApolloClient
method to create a client instance and basically make a query function that template can use. In this case I set to send a query on click event:
<template>
<div class="page-query">
<button @click="query">Send Query</button>
<div>{{ result }}</div>
</div>
</template>
The response comes back and save it to the result
variable and Vue updates the template.
Notes
When we created that Apollo client, we gave it an instance of InMemoryCache, which means by default it would start caching all of the previously requested response so if the UI request the same query, it would not need to send another network request and give you that instant feedback. However if you do need to get refresh response every time then you can pass a value to fetch-policy
. You can read more about other acceptable values in Apollo Doc. Be mindful that the official Apollo client pushes doing things with React way but I'm using the underlying Apollo client in this post.
await apolloClient.query({
query: gql`
query product($productId: ID!) {
product(id: $productId) {
title
skuNo
}
}
`,
variables: {
productId: 123,
},
fetchPolicy: 'network-only'
});
If you find it useful, please share to let other people know how to incorporate GraphQL in their Vue apps.