GraphQL.js 从 v16 升级到 v17 的完整指南
2025-07-05 07:24:31作者:霍妲思
GraphQL.js 作为 JavaScript 实现的 GraphQL 参考实现,在 v17 版本中引入了一些重要的变更和改进。本文将从技术专家的角度,详细解析这些变化,帮助开发者顺利完成版本迁移。
版本状态说明
当前 GraphQL v17 处于 alpha 阶段,本文基于 alpha 版本编写,部分内容可能会在正式版发布前有所调整。
重大变更解析
默认值处理的强化
在 v17 中,GraphQL.js 对输入字段和参数的默认值处理进行了重大改进:
- 严格验证:现在会在 schema 构建阶段就对默认值进行验证和强制类型转换
- 错误示例:
input ExampleInput { value: Int = "invalid" }
现在会直接触发验证错误 - 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
});
执行相关变更
- 增量交付支持:
execute
函数现在会对@defer
或@stream
指令抛出错误- 需要使用
experimentalExecuteIncrementally
替代
// 替换导入
import { experimentalExecuteIncrementally as execute } from 'graphql';
- 订阅函数改进:
subscribe
现在可以返回非 Promise 值- 移除了对增量交付的支持(需使用
if
参数在订阅操作中禁用)
类型系统调整
-
移除的枚举类型:
TokenKindEnum
、KindEnum
和DirectiveLocationEnum
- 改用
Kind
、TokenKind
和DirectiveLocation
-
模块重组:
- 移除了
graphql/subscription
模块 - 所有执行相关导出已统一到
graphql/execution
- 移除了
-
AST 集合表示:
- 空的 AST 集合现在用
undefined
表示,而非空数组
- 空的 AST 集合现在用
变量值结构变更
Info.variableValues
的结构已更改为包含 sources
和 coerced
键的对象:
sources
包含变量强制转换前的信息signature
包含变量名、输入类型和默认值
流式指令限制
- 字段唯一性:
@stream
指令不能出现在同一字段的多个实例上 - 参数非空:
initialCount
参数现在是非空的
输入值处理优化
coerceInputValue
现在在出错时返回 undefined
(早期中止以优化性能)。如需获取具体错误,请使用新的 validateInputValue
辅助函数。
已移除的功能
以下是 v17 中完全移除的功能列表:
-
废弃函数移除:
getOperationType
→ 改用GraphQLSchema
实例的getRootType
getVisitFn
→ 改用getEnterLeaveForKind
printError
和formatError
→ 改用错误的toString
或toJSON
方法assertValidName
和isValidNameError
→ 改用assertName
assertValidExecutionArguments
→ 改用assertValidSchema
-
其他移除:
TypeInfo
中的getFieldDefFn
validate
中的TypeInfo
导出
新功能与实验性特性
增量交付(实验性)
- 必须使用
experimentalExecuteIncrementally()
- 新增
enableEarlyExecution
配置选项 - 在
execute()
中使用@defer
/@stream
指令会抛出错误
片段参数(实验性)
- 通过
experimentalFragmentArguments
配置选项启用 - 新增
Kind.FRAGMENT_ARGUMENT
用于访问 - 新增
coerceInputLiteral()
函数处理片段参数
其他新功能
-
执行控制:
- 新增
hideSuggestions
选项隐藏错误消息中的 schema 建议 - 新增
abortSignal
支持取消操作
- 新增
-
扩展支持:
extensions
现在支持symbol
键- 解析器函数可以返回异步可迭代对象
-
辅助工具:
- 新增
validateInputValue
和validateInputLiteral
- 新增
replaceVariableValues
处理复杂标量中的变量 - 新增
printDirective
辅助函数
- 新增
升级建议
- 逐步迁移:先在开发环境测试 v17,再部署到生产
- 类型检查:利用 TypeScript 检查所有废弃 API 的使用
- 测试覆盖:确保测试覆盖所有涉及变更的功能点
- 性能监控:关注输入值处理变更可能带来的性能影响
通过理解这些变更并遵循本指南,开发者可以顺利将应用从 GraphQL.js v16 升级到 v17,同时利用新版本带来的改进和功能增强。