Apollo-codegen场景下,.graphql文件中GraphQL查询的使用方法咨询
嘿,这个问题我刚好处理过,给你一步步拆解怎么把GraphQL查询移到.graphql文件,同时配合apollo-codegen生成类型并在TypeScript里调用:
.graphql文件结构 先把原来的订阅查询从TS文件里抽出来,放到单独的.graphql文件中。比如创建src/graphql/subscriptions.graphql,内容直接写纯GraphQL代码:
subscription suppliers { suppliers { id name } }
建议按查询类型(查询/突变/订阅)或者业务模块来划分文件,比如queries.graphql、mutations.graphql,这样后期维护更清晰。
apollo-codegen生成类型 首先确保你安装了必要的代码生成依赖(根据你的客户端库调整,比如React用typescript-react-apollo,Angular用typescript-apollo-angular):
npm install --save-dev @graphql-codegen/cli @graphql-codegen/typescript @graphql-codegen/typescript-operations @graphql-codegen/typescript-react-apollo
然后在项目根目录创建codegen.yml配置文件,指定你的Schema来源、.graphql文件路径,以及生成的TS文件位置:
overwrite: true schema: "https://your-graphql-api-endpoint.com/graphql" # 也可以本地Schema文件路径 documents: "src/graphql/**/*.graphql" # 匹配所有.graphql文件 generates: src/generated/graphql.ts: plugins: - "typescript" - "typescript-operations" - "typescript-react-apollo" # 对应你的客户端框架,按需替换
接着在package.json里加个脚本方便生成:
{ "scripts": { "codegen": "graphql-codegen --config codegen.yml" } }
运行npm run codegen,就能在src/generated/graphql.ts里得到自动生成的类型和对应的查询/订阅文档对象了。
.graphql里的查询 现在你不用再写gql模板字符串了,直接导入生成的类型和文档对象即可。比如用Apollo Client原生调用订阅:
import { ApolloClient, InMemoryCache } from '@apollo/client'; // 导入生成的订阅类型和文档 import { SuppliersSubscription, SuppliersDocument } from './generated/graphql'; // 初始化Apollo Client const client = new ApolloClient({ uri: 'https://your-graphql-api-endpoint.com/graphql', cache: new InMemoryCache(), }); // 发起订阅 const subscription = client.subscribe<SuppliersSubscription>({ query: SuppliersDocument, }).subscribe({ next(data) { // 这里data的类型是完全自动推导的,编辑器会有完整的代码提示 console.log('获取到供应商数据:', data.data?.suppliers); }, error(err) { console.error('订阅出错:', err); }, }); // 记得在合适的时机取消订阅,比如组件销毁时 // subscription.unsubscribe();
如果是React项目,直接用useSubscription钩子更方便:
import { useSubscription } from '@apollo/client'; import { SuppliersSubscription, SuppliersDocument } from './generated/graphql'; export default function SuppliersList() { const { data, loading, error } = useSubscription<SuppliersSubscription>(SuppliersDocument); if (loading) return <div>加载中...</div>; if (error) return <div>订阅出错:{error.message}</div>; return ( <ul> {data?.suppliers?.map(supplier => ( <li key={supplier.id}>{supplier.name}</li> ))} </ul> ); }
.graphql文件的问题(可选) 如果TypeScript编译器报错说无法导入.graphql文件,可以在项目根目录创建graphql.d.ts声明文件:
declare module '*.graphql' { import { DocumentNode } from 'graphql'; const value: DocumentNode; export default value; }
不过其实用apollo-codegen生成的Document对象已经足够,这个步骤主要是为了直接导入.graphql文件的场景。
内容的提问来源于stack exchange,提问作者Ced

