If you are knee-deep in the world of web development, chances are you have crossed paths with GraphQL and Apollo Client. This dynamic duo has revolutionized how developers interact with data on the frontend. However Apollo Client does have a flaw, "How do I connect to multiple GraphQL endpoints using a single client instance? This post will explain a few ways to achieve just that.
Note: For the sake of brevity, 'query' will refer to any GraphQL operation; Query, Mutation or Subscription.
ApolloLink.split()
The native approach is to make use of the split
function provided by the @apollo/client
. This will enable your link chain to branch to one of two HttpLink
s based on the result of a boolean check.
import { ApolloClient, ApolloLink, HttpLink } from '@apollo/client';
const endpoint1 = new HttpLink({
uri: 'http://endpoint1.com/graphql',
...
});
const endpoint2 = new HttpLink({
uri: 'http://endpoint2.com/graphql',
...
});
const client = new ApolloClient({
link: ApolloLink.split(
operation => operation.getContext().apiName === 'end1', // boolean check
endpoint1, // if true
endpoint2 // if fa
)
...
});
// pass the apiName via the context in your Query
useQuery(QUERY, { variables, context: { apiName: 'end1' } });
In this example, the boolean check is based on a context variable, however the test can be anything. The split
function is simple to implement but is limited to only two GQL connections.
Dynamic HttpLink
But now what if a application serves as the frontend for a suite of microservices? Well, by expanding the use of the operation context
the endpoint in the HttpLink
can be set dynamically.
import { ApolloClient, createHttpLink } from '@apollo/client';
const httpLink = createHttpLink({
uri: ({ getContext }) => {
const { apiName } = getContext();
if (apiName === 'end1') return 'http://endpoint1.com/graphql';
if (apiName === 'end2') return 'http://endpoint2.com/graphql';
if (apiName === 'end3') return 'http://endpoint3.com/graphql';
...
}
});
const client = new ApolloClient({
link: httpLink
...
});
// pass the apiName via the context in your Query
useQuery(QUERY, { variables, context: { apiName: 'end1' } });
useQuery(QUERY, { variables, context: { apiName: 'end2' } });
This solution is also relatively simple and allows for expendability as new microservices are added to the suite that the client app has to connect to.
The disadvantage of both of these approaches is that the developer has to include the apiName
in the context every time that useQuery
. Personally I found this approach lead to a messy implementation. I mean declaring the context object on every request is so repetitive.
Apollo MultiAPILink
I wanted a solution that was more intuitive though, something that removed the need to declare the API every time a useQuery
was used, enter @habx/apollo-multi-endpoint-link. This library allows the API to be declared on the GQL query as a directive, instead of every time useQuery
is called.
const QUERY1 = gql`
query Users @api(name: end1) {
users { id name }
}
`;
const QUERY2 = gql`
query Companies @api(name: end2) {
companies { id name code }
}
`;
The @api(name: end1)
informs the library which endpoint to use based on configuration.
Note: The directive is removed from the query before it is sent to the server.
import { ApolloClient, createHttpLink } from '@apollo/client';
import { MultiAPILink } from '@habx/apollo-multi-endpoint-link';
const multiHttpLink = new MultiAPILink({
endpoints: {
end1: 'http://endpoint1.com',
end2: 'http://endpoint2.com',
end3: 'http://endpoint3.com',
...
},
createHttpLink: () => createHttpLink()
});
const client = new ApolloClient({
link: multiHttpLink
...
});
// Now use the query without any additional api config
useQuery(QUERY1);
useQuery(QUERY2);
The MultiAPILink
matches the API name with the relevant endpoint. Since the API is declared on the query, it doesn't have to be repeated in every useQuery
, leaving code much cleaner and containing less duplication.
Conclusion
In summary, its definitely possible to have multiple endpoints in a single Apollo Client instance.
Sources
Github: @habx/apollo-multi-endpoint-link
Apollo Link Overview
Apollo Link - Directional Composition
Top comments (0)