GraphQL Apollo Client with Angular v6.x or v7.x and JWT tokens
I have talked about the server-side implementation of GraphQL in my earlier article and I have received many requests to write about the client-side implementation, which I have used Apollo Client in Angular 6.x application.
In this article, we will talk about Apollo Client for Angular, its dependencies and what packages I have used to in my application to build my Angular 6.x Application.
Apollo Client for Angular
As per their website,
Apollo Client is the ultra-flexible, community-driven GraphQL client for Angular, JavaScript, and native platforms. It is designed from the ground up to make it easy to build UI components that fetch data with GraphQL.
Which simply means that using Apollo Client will help you set up everything you need to connect to your GraphQL server with bare minimum code without worrying too much of GraphQL implementation on the client. Apollo Client supports the most popular frameworks and libraries like Angular, React, Vue, Meteor, Ember and Polymer.
To get started with Apollo Client for Angular, you need to install below npm packages
apollo-angular
A full-fledged Apollo Client package implemented for the applications built in Angular framework.
apollo-link
A network interface for Apollo Client
apollo-link-context
Easily set a context on your operation, which is used by other links further down the chain.
apollo-link-error
Handle and inspect errors in your GraphQL network stack.
apollo-link-http
Get GraphQL results over a network using HTTP fetch.
apollo-link-ws
Send GraphQL operations over a WebSocket. Works with GraphQL Subscriptions.
graphql-tag
Helpful utilities for parsing GraphQL queries
Setting up the client
Setting up the Apollo client in Angular application is very simple and easy, all you have to do is add Apollo Angular Client in your src/app/app.module.ts
file.
Setting up HttpLink
In the app.module.ts
file, you can create a GraphQL HttpLink to access GraphQL over HTTP
const http = new HttpLink({
uri: `http://your_graphql_endpoint`
});
Setting up WebSocket Link
The WebSocketLink in Apollo lets you connect with your GraphQL server using Web Sockets.
const ws = new WebSocketLink({
uri: `ws://your_graphql_endpoint`,
options: {
reconnect: true
}
});
Setting up context
The context in Apollo Client lets you manage request headers and set the authorization token in every request made by Apollo Client to the GraphQL server.
const authContext = setContext(async (request, previousContext) => {
// get the token from session or storage
const token = await this.session.getToken(); if(!token) {
return {}
} // Set the Authorization headers
return {
headers: {Authorization: `Bearer ${token}`}
}
});
Setting up the Error Handlers
Apollo Client comes with prebuilt Error and Exception Handler which can catch all the Errors and Expectations made my GraphQL server.
const error = onError(({graphQLErrors, networkError, response, operation}) => {
// Checking GraphQL Errors
if(graphQLErrors) {
graphQLErrors.map(({message, path, type}) => { if(type === 'INVALID_TOKEN') {
this.session.destroy();
} if(type === 'UNAUTHENTICATED') {
this.session.destroy();
}
console.log(`[GraphQL Error]: Type: ${type}, Message: ${message}`, path);
});
} // Checking in Network Errors
if(networkError) {
console.log(`[Network Error]:`, networkError);
}
});
Setting up afterwareLink
Apollo Links also allows capturing all the responses from GraphQL server to one place, which can be helpful to set tokens and other required variables on the client side.
const afterwareLink = new ApolloLink((operation, forward) => {
return forward(operation).map(response => { const {
response: { headers }
} = operation.getContext(); if(headers) {
const _token = headers.get('Authorization');
if(_token && _token !== 'null') {
const payload = getPayload(_token);
this.session.setToken(_token);
}
} return response;
});
});
Splitting the HTTP and WebSocket
We need to split the ApolloLink for both the transport HTTP and WebSocket and using thesplit
method from apollo-link
package.
const link = split(({query}) => {
const { kind, operation } = getMainDefinition(query);
return kind === 'OperationDefinition' && operation === 'subscription';
}, ws, ApolloLink.from([authContext, error, afterwareLink, http]));
Joining all the pieces and creating final ApolloLink
We have created separate links and implemented various functions for these links such as handling all the requests being sent by ApolloClient with its headers, Error Messages thrown by the ApolloServer, Capturing all the responses received by ApolloClient with its headers and implement multichannel Link to the GraphQL sever on HTTP and WebSocket.
Not its time to join these pieces together and create the final ApolloLink using create
method.
apollo.create({
link: link,
cache: new InMemoryCache(),
defaultOptions: {
query: {
fetchPolicy: 'network-only'
}
}
});
Putting everything into theapp.module.ts
file.
The above code is having all the required implementation for your application using Apollo Angular Client for a RESTful based web application which sends and received JWT tokens in every request.
Define GraphQL Fragments
A GraphQL Fragment is a shared piece of Query logic and has two main principles
- Sharing fields between multiple queries, mutations or subscriptions.
- Breaking your queries up to allow you to co-locate field access with the places they are used.
To define GraphQL Fragments I have created a new file src/app/fragments.ts
// src/app/fragments.tsimport gql from 'graphql-tag';
// A GraphQL Fragment on User type
export const userFields = gql`
fragment userFields on User {
first_name
last_name
password
bio
}
`;
export const postFields = gql`
fragment postFields on Post {
author {
..userFeilds
}
title
description
banner
}
${userFields}
`;
Define GraphhQL Queries, Mutations and Subscriptions
I have created a new file src/app/graphql.ts
to define all the GraphQL Queries, Mutations and Subscriptions
// src/app/graphql.tsimport gql from 'graphql-tag';
import { userFields, postFields } from './fragments';export const QUERY_USERS = gql`
query users {
users {
...userFields
}
}
${userFields}
`;export const MUTATION_LOGIN = gql`
mutation login($email: String!, $password: String!){
login(email: $email, password: $password){
...userFields
}
}
${userFields}
`;export const SUBSCRIPTION_POST = gql`
subscription post {
post {
...postFields
}
}
${postFields}
`;
Queries, Mutations and Subscription
In Apollo client making a query to GraphQL endpoint is easy and simple, I have used Apollo from apollo-angular as a dependency in my services and used the same to make query, mutation and subscription requests
Conclusion
Apollo Makes using GraphQL simple and easy and its backed by a huge community which helping people like us to adapt and start using GraphQL for our applications.
Let me know your implementation of GraphQL on client-side, I would love to learn more about the same.
Share with your developer friends and help the community.
Don’t forget to clap if it helps you.