这是我在这里的第一篇讨论文章。我通过奥德赛学会了Apollo
+GraphQL
。目前,我正在使用Next.js构建自己的项目,该项目需要从2GraphQL端点获取数据。
我的问题是:如何使用ApolloClient
从多个GraphQL端点获取数据?
以下是我的第一个端点的代码:
import { ApolloClient, InMemoryCache, createHttpLink } from "@apollo/client";
const client = new ApolloClient({
ssrMode: true,
link: createHttpLink({
uri: "https://api.hashnode.com/",
credentials: "same-origin",
headers: {
Authorization: process.env.HASHNODE_AUTH,
},
}),
cache: new InMemoryCache(),
});
export default client;
你试图实现的目标有点违背阿波罗的"一张图";方法看看网关和联盟-https://www.apollographql.com/docs/federation/
话虽如此,一些巧妙的解决方案是可能的,但您需要维护一个更复杂的结构,并在每个查询中指定端点,这会破坏内置机制,并可能导致优化问题。
//Declare your endpoints
const endpoint1 = new HttpLink({
uri: 'https://api.hashnode.com/graphql',
...
})
const endpoint2 = new HttpLink({
uri: 'endpoint2/graphql',
...
})
//pass them to apollo-client config
const client = new ApolloClient({
link: ApolloLink.split(
operation => operation.getContext().clientName === 'endpoint2',
endpoint2, //if above
endpoint1
)
...
})
//pass client name in query/mutation
useQuery(QUERY, {variables, context: {clientName: 'endpoint2'}})
这个程序包似乎可以满足您的要求:https://github.com/habx/apollo-multi-endpoint-link
此外,请查看此处的讨论:https://github.com/apollographql/apollo-client/issues/84
今天遇到了同样的问题。我想让它动态,所以这就是我提出的:
export type DynamicLinkClientName = "aApp" | "bApp" | "graphqlApp";
type Link = RestLink | HttpLink;
type DynamicLink = { link: Link; name: DynamicLinkClientName };
const LINK_MAP: DynamicLink[] = [
{ link: aRestLink, name: "aApp" },
{ link: bAppRestLink, name: "bApp" },
{ link: graphqlAppLink, name: "graphqlApp" },
];
const isClientFromContext = (client: string) => (op: Operation) =>
op.getContext().client === client;
const DynamicApolloLink = LINK_MAP.reduce<ApolloLink | undefined>(
(prevLink, nextLink) => {
// When no name is specified, fallback to defaultLink.
if (!prevLink) {
return ApolloLink.split(
isClientFromContext(nextLink.name),
nextLink.link,
defaultLink
);
}
return ApolloLink.split(
isClientFromContext(nextLink.name),
nextLink.link,
prevLink
);
},
undefined
) as ApolloLink;
非常喜欢Pete的解决方案,因为它只允许2个以上的端点。
为了更好地进行类型检查,我决定编写自己的版本。
以下是我对他的解决方案的看法:
字体:
const defaultClient: keyof typeof clients = "heroku";
const clients = {
"heroku": new HttpLink({ uri: "https://endpointURLForHeroku" }),
"lists": new HttpLink({uri: "https://endpointURLForLists" })
}
const isRequestedClient = (clientName: string) => (op: Operation) =>
op.getContext().clientName === clientName;
const ClientResolverLink = Object.entries(clients)
.map(([clientName, Link]) => ([clientName, ApolloLink.from([Link])] as const))
.reduce(([_, PreviousLink], [clientName, NextLink]) => {
const ChainedLink = ApolloLink.split(
isRequestedClient(clientName),
NextLink,
PreviousLink
)
return [clientName, ChainedLink];
}, ["_default", clients[defaultClient]])[1]
declare module "@apollo/client" {
interface DefaultContext {
clientName: keyof typeof clients
}
}
JS:
const defaultClient = "heroku";
const clients = {
"heroku": new HttpLink({ uri: "https://endpointURLForHeroku" }),
"lists": new HttpLink({uri: "https://endpointURLForLists" })
}
const isRequestedClient = (clientName) => (op) =>
op.getContext().clientName === clientName;
const ClientResolverLink = Object.entries(clients)
.reduce(([_, PreviousLink], [clientName, NextLink]) => {
const ChainedLink = ApolloLink.split(
isRequestedClient(clientName),
NextLink,
PreviousLink
)
return [clientName, ChainedLink];
}, ["_default", clients[defaultClient]])[1]