graphql - 如何将大的graphql模式文件分成多个小文件?
问题描述
我正在使用 graphql、express-graphql 和猫鼬。我没有使用 buildSchema。下面是我用来学习 graphql 的代码,我现在对使用 apollo-server 不感兴趣。问题是我的模式文件现在变得相当大,我希望让事情变得更好。
我如何将此代码分解为多个文件?
架构.js:
const graphql = require('graphql');
const Book = require('../models/book');
const Author = require('../models/author');
const {
GraphQLObjectType,
GraphQLSchema,
GraphQLString,
GraphQLID,
GraphQLInt,
GraphQLList,
GraphQLNonNull
} = graphql;
const BookType = new GraphQLObjectType({
name: 'Book',
fields: () => ({
id: { type: GraphQLID },
name: { type: GraphQLString },
genre: { type: GraphQLString },
author: {
type: AuthorType,
resolve(parent, args) {
//find(authors, { id: parent.authorID });
return Author.findById(parent.authorID);
}
}
})
});
const AuthorType = new GraphQLObjectType({
name: 'Author',
fields: () => ({
id: { type: GraphQLID },
name: { type: GraphQLString },
age: { type: GraphQLInt },
books: {
type: new GraphQLList(BookType),
resolve(parent, args) {
return Book.find({ authorID: parent.id });
}
}
})
});
const RootQuery = new GraphQLObjectType({
name: 'RootQueryType',
fields: {
book: {
type: BookType,
args: { id: { type: GraphQLID } },
resolve(parent, args) {
return Book.findById(args.id);
}
},
author: {
type: AuthorType,
args: { id: { type: GraphQLID } },
resolve(parent, args) {
return Author.findById(args.id);
}
},
books: {
type: new GraphQLList(BookType),
resolve(parent, args) {
return Book.find({});
}
},
authors: {
type: new GraphQLList(AuthorType),
resolve(parent, args) {
return Author.find({});
}
}
}
});
const Mutation = new GraphQLObjectType({
name: 'Mutation',
fields: {
addAuthor: {
type: AuthorType,
args: {
name: { type: new GraphQLNonNull(GraphQLString) },
age: { type: new GraphQLNonNull(GraphQLInt) }
},
resolve(parent, args) {
let author = new Author({
name: args.name,
age: args.age
});
return author.save();
}
},
addBook: {
type: BookType,
args: {
name: { type: new GraphQLNonNull(GraphQLString) },
genre: { type: new GraphQLNonNull(GraphQLString) },
authorID: { type: new GraphQLNonNull(GraphQLID) }
},
resolve(parent, args) {
let book = new Book({
name: args.name,
genre: args.genre,
authorID: args.authorID
});
return book.save();
}
}
}
});
module.exports = new GraphQLSchema({
query: RootQuery,
mutation: Mutation
});
我如何在 app.js 中调用架构:
app.use('/api', graphqlHTTP( async req => ({
schema,
graphiql: { headerEditorEnabled: true }
})));
解决方案
这都可以归结为经典的 JS 导入和导出。您在这里所做的一切都可以在单独的文件中定义和导出,并相应地导入您需要的地方。我不完全确定我会鼓励以这种方式思考您的架构,但要回答您的问题:
您可以创建以下文件夹结构:
typedefs/bookType.js
typedefs/authorType.js
typedefs/query.js
typedefs/mutation.js
这允许您将架构类型定义组织为更小的、单独的、可导出的单元。
例如,您的 bookType.js 文件可能如下所示:
// Declare your imports at the top
import { AuthorType } from './authorType';
import Author from '../models/author';
// Note the export
export const BookType = new GraphQLObjectType({
name: 'Book',
fields: () => ({
id: { type: GraphQLID },
name: { type: GraphQLString },
genre: { type: GraphQLString },
author: {
type: AuthorType,
resolve(parent, args) {
//find(authors, { id: parent.authorID });
return Author.findById(parent.authorID);
}
}
})
});
您的作者类型可能如下所示:
import { BookType } from './bookType';
import Book from '../models/Book';
...
export const AuthorType = new GraphQLObjectType({
name: 'Author',
fields: () => ({
id: { type: GraphQLID },
name: { type: GraphQLString },
age: { type: GraphQLInt },
books: {
type: new GraphQLList(BookType),
resolve(parent, args) {
return Book.find({ authorID: parent.id });
}
}
})
});
需要注意的几点:
注意循环依赖。BookType 将需要导入 AuthorType,而 AuthorType 将需要导入 BookType。循环依赖可能导致难以处理的错误,此外还可能导致堆/内存问题并破坏类型检查器(如 Typescript 或 FlowType)。
如果您采用这种方法,您的架构将变得更难推理。与 DB 模型不同,在 DB 模型中,每个模型/表都是其自己的独立实体,几乎没有(如果有的话)依赖关系,当您的 GraphQL 模式可以轻松表达类型之间的数据相互依赖关系时,它真的会蓬勃发展。这就是为什么,鉴于个人经验尝试了几次,我不会鼓励这种方式来编写你的模式。请参阅我在此处详细说明此问题的另一篇文章:https ://stackoverflow.com/a/65035430/4301222
推荐阅读
- json - json_decode() 在 Laravel Blade 模板中直接调用时中断 - (期望字符串,给定对象)
- python - 'index 0 is out of bounds for axis 0 with size 0' 是什么意思,我该如何解决这个错误?
- java - Spark 3.1-java 在 GCP 中运行时引发内部错误 - Dataproc 集群
- redirect - 简单的 301 重定向 - 为什么它不起作用?
- javascript - 如何在不重写代码的情况下使用一个 CSS 模块并为其添加另一种样式?
- java - 嗨,我是 spring 新手,我想在我的索引页面中创建一个输入,该输入可以作为我的控制器的 getmapping 的值我该怎么做
- android - Fastlane android 构建:缺少 index.android.bundle
- certificate - RSA2048签名输出Base64length
- javascript - Firebase 用户身份验证
- .net - (DOCKER) 服务不会从特定用户开始