gql 和 buildSchema 有什么区别?

spi*_*kus 2 graphql graphql-js apollo-server graphql-tag

graphql-js buildSchemaapollo-server 有什么区别gql?他们似乎做着非常相似的工作。

spi*_*kus 5

首先请注意,apollo-server实际上是从graphql-taggql重新导出的。是一个约 150 行的包,默认且几乎唯一有用的导出是.graphql-taggql

简单介绍一下背景知识:该graphql-js包提供了 Javascript 中 GraphQL 的官方参考实现。它基本上提供了两件重要的事情:

  1. graphql函数将处理针对GraphQLSchema对象的任何 GraphQL 查询(GraphQLSchema 对象是 graphql-js 表示解析模式的方式)。
  2. 一堆实用函数和类型,用于从字符串构建和验证GraphQLSchema函数使用的对象。graphql

现在,这是最终让我困惑的部分:在 中graphql-js,获取字符串并将其转换为GraphQLSchema对象是一个两步过程:

  • 第 1 步:字符串 -> AST(由函数完成parse)。
  • 第2步:AST -> GraphQLSchema(由buildASTSchema函数完成)。

这是因为 AST(抽象语法树)对于许多其他工具很有用,这些工​​具甚至不一定了解 GraphQL(例如,请参阅https://astexplorer.net/),而 GraphQLSchema 只是对 graphql-js 和相关软件有意义。

graphql-js 公开了执行这两个步骤的函数,这些函数被下游实现者(如 Apollo)重用。buildSchema只是一个组合这两个步骤的方便包装。从字面上看是这样的

/**
 * A helper function to build a GraphQLSchema directly from a source
 * document.
 */
export function buildSchema(source: string | Source): GraphQLSchema {
  return buildASTSchema(parse(source));
}
Run Code Online (Sandbox Code Playgroud)

gql另一方面,的输出只是 AST 部分,与 graphql-jsparse函数的输出相同。由于上述原因,gql不会直接返回 a :AST 很有用(注意还执行一些基本操作,例如状态缓存,并将架构字符串数组合并到单个 AST 结果中...)。最终 AST 必须转换为正确的模式,并且 apollo-server 在服务器实例化时(大概)会执行此操作。GraphQLSchemagql

为了显示这种关系,我们可以将gql(与 相同parse)的输出运行一遍buildASTSchema(就像buildSchema那样),然后将其传递给graphql,它的工作原理是相同的:

import { graphql, buildSchema, buildASTSchema } from 'graphql';
import { gql } from 'apollo-server'; // equivalent to 'import gql from graphql-tag'

const schemaString = `
  type Query {
    hello: String!
  }
`;

const a = buildASTSchema(gql(schemaString));
const b = buildSchema(schemaString);

graphql(a, '{ hello }', { hello: () => 'Hello world!' }).then((response) => {
  console.log(response);
});
graphql(b, '{ hello }', { hello: () => 'Hello world!' }).then((response) => {
  console.log(response);
});
Run Code Online (Sandbox Code Playgroud)

给出:

{ data: [Object: null prototype] { hello: 'Hello world!' } }
{ data: [Object: null prototype] { hello: 'Hello world!' } }
Run Code Online (Sandbox Code Playgroud)