首页
/ GraphQL.js 从 v16 升级到 v17 的完整指南

GraphQL.js 从 v16 升级到 v17 的完整指南

2025-07-05 07:24:31作者:霍妲思

GraphQL.js 作为 JavaScript 实现的 GraphQL 参考实现,在 v17 版本中引入了一些重要的变更和改进。本文将从技术专家的角度,详细解析这些变化,帮助开发者顺利完成版本迁移。

版本状态说明

当前 GraphQL v17 处于 alpha 阶段,本文基于 alpha 版本编写,部分内容可能会在正式版发布前有所调整。

重大变更解析

默认值处理的强化

在 v17 中,GraphQL.js 对输入字段和参数的默认值处理进行了重大改进:

  1. 严格验证:现在会在 schema 构建阶段就对默认值进行验证和强制类型转换
  2. 错误示例input ExampleInput { value: Int = "invalid" } 现在会直接触发验证错误
  3. API 变更
    • 废弃 astFromValue,推荐使用 valueToLiteral
    • 新增 default: { value: <externalValue> } 语法
// 旧方式 (已废弃)
const defaultValue = astFromValue(internalValue, type);
// 新方式
const defaultValue = valueToLiteral(externalValue, type);

错误构造器简化

GraphQLError 构造器现在只接受消息和选项对象作为参数:

// 旧方式
new GraphQLError('message', 'source', 'positions', 'path', 'originalError', 'extensions');

// 新方式
new GraphQLError('message', { 
  source, 
  positions, 
  path, 
  originalError, 
  extensions 
});

执行相关变更

  1. 增量交付支持
    • execute 函数现在会对 @defer@stream 指令抛出错误
    • 需要使用 experimentalExecuteIncrementally 替代
// 替换导入
import { experimentalExecuteIncrementally as execute } from 'graphql';
  1. 订阅函数改进
    • subscribe 现在可以返回非 Promise 值
    • 移除了对增量交付的支持(需使用 if 参数在订阅操作中禁用)

类型系统调整

  1. 移除的枚举类型

    • TokenKindEnumKindEnumDirectiveLocationEnum
    • 改用 KindTokenKindDirectiveLocation
  2. 模块重组

    • 移除了 graphql/subscription 模块
    • 所有执行相关导出已统一到 graphql/execution
  3. AST 集合表示

    • 空的 AST 集合现在用 undefined 表示,而非空数组

变量值结构变更

Info.variableValues 的结构已更改为包含 sourcescoerced 键的对象:

  • sources 包含变量强制转换前的信息
  • signature 包含变量名、输入类型和默认值

流式指令限制

  1. 字段唯一性@stream 指令不能出现在同一字段的多个实例上
  2. 参数非空initialCount 参数现在是非空的

输入值处理优化

coerceInputValue 现在在出错时返回 undefined(早期中止以优化性能)。如需获取具体错误,请使用新的 validateInputValue 辅助函数。

已移除的功能

以下是 v17 中完全移除的功能列表:

  1. 废弃函数移除:

    • getOperationType → 改用 GraphQLSchema 实例的 getRootType
    • getVisitFn → 改用 getEnterLeaveForKind
    • printErrorformatError → 改用错误的 toStringtoJSON 方法
    • assertValidNameisValidNameError → 改用 assertName
    • assertValidExecutionArguments → 改用 assertValidSchema
  2. 其他移除:

    • TypeInfo 中的 getFieldDefFn
    • validate 中的 TypeInfo 导出

新功能与实验性特性

增量交付(实验性)

  1. 必须使用 experimentalExecuteIncrementally()
  2. 新增 enableEarlyExecution 配置选项
  3. execute() 中使用 @defer/@stream 指令会抛出错误

片段参数(实验性)

  1. 通过 experimentalFragmentArguments 配置选项启用
  2. 新增 Kind.FRAGMENT_ARGUMENT 用于访问
  3. 新增 coerceInputLiteral() 函数处理片段参数

其他新功能

  1. 执行控制

    • 新增 hideSuggestions 选项隐藏错误消息中的 schema 建议
    • 新增 abortSignal 支持取消操作
  2. 扩展支持

    • extensions 现在支持 symbol
    • 解析器函数可以返回异步可迭代对象
  3. 辅助工具

    • 新增 validateInputValuevalidateInputLiteral
    • 新增 replaceVariableValues 处理复杂标量中的变量
    • 新增 printDirective 辅助函数

升级建议

  1. 逐步迁移:先在开发环境测试 v17,再部署到生产
  2. 类型检查:利用 TypeScript 检查所有废弃 API 的使用
  3. 测试覆盖:确保测试覆盖所有涉及变更的功能点
  4. 性能监控:关注输入值处理变更可能带来的性能影响

通过理解这些变更并遵循本指南,开发者可以顺利将应用从 GraphQL.js v16 升级到 v17,同时利用新版本带来的改进和功能增强。