如何从其他schema.graphql导入类型?多.graphql文件类型导入问题(#import不适用)
嘿,我来帮你搞定这两个GraphQL schema拆分与导入的问题,这在项目规模变大后确实是很常见的需求!
具体的实现方式取决于你使用的GraphQL工具链,这里分享几个最常用的方案:
使用GraphQL Code Generator:这是最便捷的方式之一,它支持原生的
#import语法。首先安装依赖:npm install @graphql-codegen/cli @graphql-codegen/schema-ast --save-dev然后在项目根目录创建
codegen.yml配置文件:schema: "./src/**/*.graphql" generates: ./src/merged-schema.graphql: plugins: - schema-ast之后你就可以在schema文件里直接导入其他文件了,比如在
post.graphql里写:#import "./user.graphql" type Post { id: ID! author: User! content: String! }最后运行
npx graphql-codegen就能生成合并后的完整schema。使用Apollo Server(v3及以上):Apollo支持直接传入多个schema文件的内容数组。你可以用
fs模块读取所有schema文件,再传给makeExecutableSchema:const { makeExecutableSchema } = require('@graphql-tools/schema'); const fs = require('fs'); const path = require('path'); // 读取所有schema文件 const userSchema = fs.readFileSync(path.join(__dirname, './user.graphql'), 'utf8'); const postSchema = fs.readFileSync(path.join(__dirname, './post.graphql'), 'utf8'); const schema = makeExecutableSchema({ typeDefs: [userSchema, postSchema] });手动合并(小型项目适用):如果你的项目很小,不想引入额外工具,直接用Node.js的
fs模块读取所有schema文件,拼接成一个字符串再创建schema即可,原理和上面Apollo的方式类似,只是更简化。
如果#import语法在你的工具链里不支持(比如某些老版本的框架),或者你只需要导入目标文件里的部分类型而非全部,试试这些方案:
使用GraphQL Tools的类型筛选与合并:借助
@graphql-tools/schema提供的工具,你可以解析源schema的AST,提取出需要的类型,再和目标schema合并:const { buildASTSchema, print, mergeTypeDefs } = require('@graphql-tools/schema'); const { loadSchemaSync } = require('@graphql-tools/load'); const { GraphQLFileLoader } = require('@graphql-tools/graphql-file-loader'); // 加载源schema文件 const sourceSchema = loadSchemaSync('./source.graphql', { loaders: [new GraphQLFileLoader()] }); // 提取你需要的类型(比如User和Comment) const selectedTypes = ['User', 'Comment'].map(typeName => { const typeNode = sourceSchema.getType(typeName).astNode; return print(typeNode); }); // 加载目标schema文件 const targetSchema = loadSchemaSync('./target.graphql', { loaders: [new GraphQLFileLoader()] }); // 合并提取的类型和目标schema const finalTypeDefs = mergeTypeDefs([...selectedTypes, targetSchema]);用GraphQL Code Generator的筛选规则:如果你用Code Generator但不想导入整个文件,可以在配置里指定只包含特定类型:
schema: - './source.graphql': include: - User - Comment - './target.graphql' generates: ./src/merged-schema.graphql: plugins: - schema-ast这样生成的schema里只会包含
source.graphql中指定的类型,以及target.graphql的全部内容。临时方案:手动提取:如果只是临时需求,或者项目工具链限制较多,你可以直接把需要的类型从源文件复制到目标文件里。虽然不够优雅,但能快速解决问题,后续再考虑用工具优化。
内容的提问来源于stack exchange,提问作者Antonio

