同一服务器上用Apollo Client访问PostGraphile(库模式)的问题
问题解答
你的核心思路是对的——通过复用PostGraphile生成的Schema和解析器实现内部调用,避免网络跳转和重复认证,但当前的实现路径有误:从codegen的introspection文件重建的Schema只有类型定义,没有PostGraphile自动生成的数据库操作解析器,所以无法执行实际的数据库读写,导致静默失败。
不需要手动编写解析器,PostGraphile本身就能直接提供包含完整解析逻辑的可执行Schema,正确的实现方式如下:
1. 从PostGraphile实例直接获取可执行Schema
调整你的PostGraphile初始化代码,保留实例引用并导出其生成的Schema(PostGraphile库模式生成的实例自带完整的可执行Schema,包含所有数据库操作的解析器):
let postGraphileInstance; export const postGraphileServer = () => { postGraphileInstance = postgraphile(process.env.DB_DSN, 'public', options); return postGraphileInstance; }; // 导出可执行Schema,确保PostGraphile已初始化完成 export const getPostGraphileSchema = () => { // 若Schema生成是异步的,可改用postGraphileInstance.whenSchemaReady()等待 return postGraphileInstance?.schema; };
2. 内部调用执行GraphQL操作
方式一:直接用graphql函数执行(轻量推荐)
不需要依赖Apollo Client,直接用graphql包提供的核心函数执行查询/变更,适合内部REST接口场景:
import { graphql } from 'graphql'; import { getPostGraphileSchema, postGraphileInstance } from './path-to-postgraphile-setup'; // 示例REST接口 app.post('/api/create-record', async (req, res) => { const { payload } = req.body; // 构建PostGraphile自动生成的变更语句 const mutation = ` mutation CreateRecord($input: CreateRecordInput!) { createRecord(input: $input) { record { id name } } } `; const schema = getPostGraphileSchema(); if (!schema) { return res.status(500).json({ error: 'Schema未初始化完成' }); } // 执行变更,传入PostGraphile解析器需要的上下文(如数据库连接池) const result = await graphql({ schema, source: mutation, variableValues: { input: { ...payload, clientMutationId: 'rest-internal-call' // PostGraphile变更需要的默认字段 } }, contextValue: { pgPool: postGraphileInstance.pgPool // 复用PostGraphile的数据库连接池 } }); if (result.errors) { return res.status(400).json({ errors: result.errors }); } res.json(result.data); });
方式二:用SchemaLink搭配Apollo Client(若需缓存等功能)
如果需要使用Apollo Client的缓存或其他特性,直接传入PostGraphile的可执行Schema即可,无需从introspection文件重建:
import { ApolloClient, SchemaLink, InMemoryCache } from '@apollo/client'; import { getPostGraphileSchema, postGraphileInstance } from './path-to-postgraphile-setup'; export const getInternalApolloClient = () => { const schema = getPostGraphileSchema(); if (!schema) throw new Error('Schema未就绪'); return new ApolloClient({ ssrMode: true, link: new SchemaLink({ schema, context: () => ({ pgPool: postGraphileInstance.pgPool }) }), cache: new InMemoryCache() }); };
关键总结
- 核心思路正确,但无需从introspection文件重建Schema,直接复用PostGraphile生成的完整可执行Schema即可。
- 不需要手动编写解析器,PostGraphile生成的Schema已包含所有数据库操作的解析逻辑。
- 内部调用优先使用
graphql函数,更轻量高效;若需Apollo生态特性再用SchemaLink。
内容的提问来源于stack exchange,提问作者Greg
相关产品推荐
相关产品推荐

