跳到主要内容
版本: v18.0.0

编译器架构

编译器是一组模块,旨在从整个代码库中提取 GraphQL 文档,转换/优化它们并生成构建工件。常见工件类型的示例包括优化的 GraphQL,用于持久化到您的服务器,查询的运行时表示,用于与 Relay 运行时等 GraphQL 客户端一起使用,或者为使用编译语言(Java/Swift 等)的 GraphQL 框架生成的源代码。

数据流

以下图表表示数据在编译器中的高级流程


┌─────────────┐┌─────────────┐
GraphQL ││ Schema
└─────────────┘└─────────────┘
│ │ parse
└───────┬──────┘

┌────────────────────────────┐
CompilerContext
│ │
│ ┌─────┐ ┌─────┐ ┌─────┐ │──┐
│ │ IR │ │ IR │ │ ... │ │ │
│ └─────┘ └─────┘ └─────┘ │ │
└────────────────────────────┘ │ transform/
│ │ ▲ │ optimize
│ │ └────────────┘
│ │
│ └──────────┐
│ print │ codegen
▼ ▼
┌─────────────┐ ┌─────────────┐
GraphQL │ │ Artifacts
└─────────────┘ └─────────────┘
  1. GraphQL 文本从源文件提取,并使用来自架构的信息将其“解析”为中间表示 (IR)。
  2. 一组 IR 文档构成一个 CompilerContext,然后对其进行转换和优化。
  3. 最后,GraphQL 被打印(例如,写入文件,保存到数据库等),并且生成任何工件。

数据类型和模块

编译器模块由一组核心构建块以及一个将它们打包到易于使用的 API 中的帮助程序组成。编译器中的一些主要数据类型和模块如下

  • IR(中间表示):GraphQL 文档(查询、片段、字段等)的(实际上是不可变的)表示,作为树结构,包括来自架构的类型信息。与标准 GraphQL AST(由例如 graphql-js 生成)相比,主要区别在于它编码了更多 GraphQL 语义。例如,条件分支(@include@skip)直接表示,使针对这些指令进行优化的目标更加容易(一种这样的优化是合并具有相同条件的同级字段,从而可能减少在运行时必须评估的条件数量)。
  • CompilerContext:一组 GraphQL 文档的不可变表示。它包含架构以及文档名称到文档表示(作为 IR,见上文)的映射。
  • Transform:一个“map”类型的函数,它接受一个 CompilerContext 作为输入并返回一个新的修改后的上下文作为输出。下面的例子。
  • Parser:将 GraphQL 架构和原始 GraphQL 文本转换为类型化的 IR 对象。
  • Printer:一个接受 IR 并将其转换为 GraphQL 字符串的函数。

RelayCompiler 模块是一个帮助程序类,它展示了一种组合这些原语的方法。它采用 IR 转换,并根据 IR 定义,从它们构建 CompilerContext,转换它们,并生成旨在与 Relay 运行时一起使用的输出工件。

转换

编译器的主要目标之一是为编写转换或优化 GraphQL 的工具提供一致的平台。这包括在编译时通过转换它们来实验新指令的能力。转换函数通常应该执行一种类型的修改 - 预计应用程序将在编译器实例中配置多个转换。

以下是一些包含的转换的示例

  • FlattenTransform:减少查询中多余的间接级别,在匿名片段与父类型匹配的地方内联来自它们的字段。当生成代码来读取查询的结果或处理查询结果时,这可能是有益的,因为它减少了重复的字段处理。例如
# before: `id` is processed twice
foo { # type FooType
id
... on FooType { # matches the parent type, so this is extraneous
id
}
}

# after: `id` is processed once
foo {
id
}
  • SkipRedundantNodeTransform:扁平化的更高级版本,它消除了更复杂类型的字段重复,例如当一个字段无条件和有条件地被提取,或被两个不同的子片段提取时。例如
# before: `id` processed up to 2x
foo {
bar {
id
}
... on FooType @include(if: $cond) { # can't be flattened due to conditional
id # but this field is guaranteed to be fetched regardless
}
}

# after: `id` processed at most once
foo {
bar {
id
}
}

此页面是否有用?

通过以下方式帮助我们让网站更好 回答一些快速问题.