Apollo中使用两个Schema的方法:解决类型冲突与端点区分
解决Apollo多Schema重复类型冲突与端点区分问题
一、下载多个独立Schema
首先修改apollo-codegen-config.json为数组结构,分别配置两个Schema的下载路径,避免直接合并导致冲突:
{ "schemaDownloadConfiguration": [ { "downloadMethod": { "introspection": { "endpointURL": "https://myApp.com/v1/cats/_/graphql", "httpMethod": { "POST": {} }, "includeDeprecatedInputValues": false, "outputFormat": "SDL" } }, "downloadTimeout": 60, "headers": [], "outputPath": "./graphql/cats-schema.graphqls" }, { "downloadMethod": { "introspection": { "endpointURL": "https://myApp.com/v1/dogs/_/graphql", "httpMethod": { "POST": {} }, "includeDeprecatedInputValues": false, "outputFormat": "SDL" } }, "downloadTimeout": 60, "headers": [], "outputPath": "./graphql/dogs-schema.graphqls" } ] }
执行Apollo代码生成的下载命令后,两个Schema会被分别保存到指定路径,不会互相覆盖。
二、处理重复类型冲突
使用@graphql-codegen的rename插件,为不同Schema的类型添加专属前缀(如Cats_、Dogs_),消除命名冲突。创建codegen.yml配置文件:
schema: - ./graphql/cats-schema.graphqls: rename: prefix: "Cats_" - ./graphql/dogs-schema.graphqls: rename: prefix: "Dogs_" generates: ./src/generated/graphql.ts: plugins: - "typescript" - "typescript-operations" - "typescript-apollo-client-helpers"
执行graphql-codegen命令后,生成的类型会自动带上前缀,比如原Date类型会变成Cats_Date和Dogs_Date,彻底解决重复命名问题。
三、配置Apollo客户端区分端点
有两种常用方案:
方案1:创建独立客户端实例
直接为每个端点创建单独的ApolloClient实例,使用时按需调用:
import { ApolloClient, InMemoryCache, HttpLink } from '@apollo/client'; // 针对cats端点的客户端 const catsClient = new ApolloClient({ link: new HttpLink({ uri: 'https://myApp.com/v1/cats/_/graphql' }), cache: new InMemoryCache(), }); // 针对dogs端点的客户端 const dogsClient = new ApolloClient({ link: new HttpLink({ uri: 'https://myApp.com/v1/dogs/_/graphql' }), cache: new InMemoryCache(), });
这种方式简单直接,适合端点逻辑相对独立的场景。
方案2:单客户端动态切换端点
通过自定义Apollo Link,根据查询的标记自动切换端点:
- 在查询定义中添加自定义标记:
# 标记该查询使用cats端点 query GetCats @endpoint(name: "cats") { cats { id name } } # 标记该查询使用dogs端点 query GetDogs @endpoint(name: "dogs") { dogs { id name } }
- 创建自定义Link处理端点切换:
import { ApolloClient, InMemoryCache, ApolloLink, from, HttpLink } from '@apollo/client'; const endpointLink = new ApolloLink((operation, forward) => { // 提取查询中的endpoint标记 const directive = operation.definitions[0].directives?.find( d => d.name.value === 'endpoint' ); const endpointName = directive?.arguments?.find(a => a.name.value === 'name')?.value.value; // 根据标记设置对应端点 if (endpointName === 'cats') { operation.setContext({ uri: 'https://myApp.com/v1/cats/_/graphql' }); } else if (endpointName === 'dogs') { operation.setContext({ uri: 'https://myApp.com/v1/dogs/_/graphql' }); } return forward(operation); }); // 构建单客户端 const client = new ApolloClient({ link: from([endpointLink, new HttpLink()]), cache: new InMemoryCache(), });
这种方式适合需要共享缓存或其他客户端配置的场景。
内容的提问来源于stack exchange,提问作者GusDev
相关产品推荐
相关产品推荐

