- 引言 — 一个看似停滞的标准动了起来
- 先把日期定准 — 两次发布的时间线
- September 2025 版本 — 四年积累的变更里值得留意的部分
- 未进入规范的部分 — defer 和 stream 仍然停留在 RFC 阶段
- GraphQL.js 17 — 什么会坏,什么会变好
- 联邦标准化的现状 — Composite Schemas 处于 Stage 0
- 那么现在该做什么
- 结语
- 参考资料
引言 — 一个看似停滞的标准动了起来
GraphQL 规范的最后一个版本,长期以来一直停在 October 2021。在此期间生态系统一直在往前走 — Apollo Federation 以及各种网关和客户端各自演进 — 但标准文档本身却停滞了将近 4 年。这样的空白足以引来「GraphQL 是不是已经进入维护模式了」这种冷嘲。
这段空白最近被两次发布打破。2025 年 9 月,September 2025 版本发布了 — 正如官方公告所说,这是 October 2021 以来的第一个版本 — 2026 年 6 月 15 日,参考实现 GraphQL.js v17 也宣布 GA。v17 的第一个 alpha 版本登上 npm 的日期是 2022 年 5 月 19 日,也就是说,摘掉 alpha 标签花了四年多的时间。
本文不带炒作地拆解这两次发布:什么真正进入了标准,什么仍然缺席(剧透: @defer 和 @stream),以及现在你的团队应该做什么。文中的每一个日期和版本号,都直接对照规范原文、npm 注册表和 GitHub 发布记录核实过。
先把日期定准 — 两次发布的时间线
GraphQL 规范 (spec.graphql.org)
2015-07 首个工作草案 (July 2015)
2021-10-26 October 2021 版本
2025-09-03 September 2025 版本 <- 时隔 3 年 10 个月
2026-06-04 当前工作草案更新(为下一版本做准备)
GraphQL.js (registry.npmjs.org 发布时间)
2022-05-19 17.0.0-alpha.1
2025-06-11 17.0.0-alpha.9
2026-05-07 17.0.0-beta.0
2026-06-02 17.0.0-rc.0
2026-06-15 17.0.0 GA <- 距 alpha 启动已过 4 年多
2026-07-03 17.0.2 (当前 latest)
16.x 仍在持续打补丁:16.13.0(2026-02-24)、16.14.2(2026-06-09)
根据规范的发布说明,September 2025 版本纳入了 October 2021 以来 30 位贡献者提交的 100 多项变更,而这次发布恰好也是距首个草案(2015 年 7 月)十年整的发布。
September 2025 版本 — 四年积累的变更里值得留意的部分
官方变更日志列出的主要变更有五项。我们逐一来看。
OneOf 输入对象 — 「输入联合类型」的标准化
GraphQL 有输出类型的联合类型,却没有输入类型的联合类型,所以没办法在 schema 里表达「按 ID 查,或者按邮箱查,二选一」这种模式。大家只能把所有字段都设为 nullable,然后在 resolver 里手动校验。这个拖了好几年的问题,在 RFC #825 下终于以 @oneOf 的形式被标准化。
input UserUniqueCondition @oneOf {
id: ID
username: String
organizationAndEmail: OrganizationAndEmailInput
}
照规范的原话,OneOf 输入对象必须恰好提供一个字段,且其值不能为 null。填两个字段会报请求错误,填一个但值是 null 也会报错。这项校验如今是规范层面的输入强制(coercion)规则,而不再是 resolver 里的代码。内省(introspection)新增了 __Type.isOneOf 字段,方便代码生成工具正确生成联合类型。
Schema Coordinates — 模式元素的寻址体系
RFC #794 给 schema 里的每一个元素都赋予了一个唯一的字符串地址。
Business 类型
Business.name 字段
SearchCriteria.filter 输入字段
SearchFilter.OPEN_NOW 枚举值
Query.searchBusiness(criteria:) 字段参数
@private 指令
@private(scope:) 指令参数
规范保证每个元素恰好拥有一个坐标。看起来微不足道,但这是工具生态的通用词汇 — schema diff、lint 规则、错误报告、用量追踪(「这个字段是谁在用」)迄今为止各家工具各写各的记法。事实上,已经有一份后续 RFC 提议把 schema 坐标塞进错误信息里。
其余变化:文档说明、deprecation 扩展、全 Unicode 支持
- 可执行文档(查询、变更)现在也可以带描述(description)了(#1170)。变更日志给出的动机很有意思,是为了 AI 消费者 — 让 LLM 理解查询意图所需的上下文,能直接放进文档本身里。
- deprecation 的适用范围扩展到了 schema 元素全体,规则也理顺了 — 比如接口没有 deprecate 的字段,实现方不能单方面 deprecate;
includeDeprecated参数改为 non-null,等等(#1053、#1142)。 - 语言语法现在支持完整的 Unicode 范围(#849)。
- 默认值的强制转换规则被重新定义(#793),执行算法的描述也做了大幅精简(比如
ExecuteSelectionSet被ExecuteCollectedFields取代)。
总的来看,这次版本不是新功能的盛宴,而是四年积压的一致性债务清偿,外加两项分量十足的语言特性(OneOf、Coordinates)。官方公告把 AI-ready 摆在最前面来包装,但实质更接近一次扎实的标准整理。
未进入规范的部分 — defer 和 stream 仍然停留在 RFC 阶段
这是这次发布里最该诚实面对的部分。@defer 和 @stream — 把响应拆成多份、逐步发送的 incremental delivery — 并不在 September 2025 版本里。我直接搜索了规范正文来确认:defer 这个词出现了 0 次。2026 年 6 月的工作草案里同样没有。
要体会这件事有多老,可以看这个: graphql 包的 npm 注册表里,experimental-stream-defer 这个实验构建从 2020 年 10 月就挂在上面,而那个 dist-tag 至今仍然指向 2021 年 12 月发布的 16.1.0 系列构建。Incremental Delivery RFC 目前处于 RFC 2(Draft)阶段 — 没有死。就在写这篇文章的这一周,规范草案也有提交(2026-07-15)。但这改变不了一个事实:这个功能「快搞定了」的状态已经持续了五年多。
为什么会拖这么久?一部分原因在于标准化执行语义(重复字段的处理、错误传播)和 payload 格式的难度,但也有实际数据并不均质的因素。在 GraphQLConf 2025 上,Meta 发布了自己的 @async 指令,理由是 @defer 会留下隐藏成本 — 也就是说,世界上把 GraphQL 用得最大规模的组织,正在试验 defer 的替代方案。标准化的目标本身还在摇摆。
实务上的含义很明确。任何今天在用 defer/stream 的技术栈,用的都还是规范之外(pre-spec)的功能,也就背着 payload 格式可能变化的风险。而它确实变了 — 就是紧接着下面的 v17 的故事。
GraphQL.js 17 — 什么会坏,什么会变好
官方升级指南 写得异常详尽,这里只挑出做判断所需的要点。
会坏的部分
- Node.js 版本要求提升到
^22.0.0 || ^24.0.0 || ^25.0.0 || >=26.0.0。如果你的环境被锁在 Node 20 及以下,到这里就走不下去了。 - 包切换到了
exports条件导出。官方入口(graphql、graphql/execution等)之外的深层导入(deep import)现在被明确写明不再有 semver 保证,而已经废弃的graphql/subscription子路径被移除了。 - 开发模式从基于
NODE_ENV的自动激活,改成了显式的 opt-in(enableDevMode()或development包条件)。 - 自定义标量 API 的命名做了整理 —
serialize、parseValue、parseLiteral会保留为已废弃的别名,coerceOutputValue、coerceInputValue、coerceInputLiteral是新名字。 subscribe()的返回类型从固定的 Promise 改成了 PromiseOrValue,假定返回 Promise 的 TypeScript 代码需要修正。
执行器分离 — execute 只做单一结果
v17 设计里最显眼的决定,是把稳定功能和实验功能做了物理上的分离。execute() 现在成了只做单一结果的稳定执行器,一旦 schema 里带有 @defer/@stream 指令,它会直接拒绝执行。要用 incremental delivery,就得调用一个名字里就写明「实验性」的独立函数。
import { experimentalExecuteIncrementally } from 'graphql';
const result = await experimentalExecuteIncrementally({ schema, document });
if ('initialResult' in result) {
send(result.initialResult);
for await (const subsequent of result.subsequentResults) {
send(subsequent);
}
} else {
send(result); // 不需要增量发送的情况
}
对在 alpha 阶段就把 defer/stream 用进生产环境的团队来说,有一个重要变化: payload 格式变了。早期 alpha 的格式用 path 和 label 来标识 payload,字段数据可能重复;现在的格式则是把 pending 项用 id 登记,再用 completed 通知完成。为了需要旧格式的宿主,legacyExecuteIncrementally() 被保留了下来,但正如名字所说,它是过渡期用的。这就是提前用规范外功能要付的账单的一个实例。
错误传播这一侧也进来了一项实验功能。给某个操作加上 @experimental_disableErrorPropagation,non-null 字段的执行错误就不会连锁地把父级也变成 null,而只让该位置本身变成 null — 这瞄准的是使用规范化缓存的客户端里,祖先节点变 null 容易被误认成真实数据更新的问题,是正在讨论中的错误行为(onError)规范议题的先行实现。这个功能同样在名字里刻着 experimental。
对运维有用的部分 — AbortSignal、diagnostics_channel、Harness
除了会坏的东西,能得到的收获也是实打实的。
- AbortSignal 支持作为一等功能进来了。请求超时、客户端断连、下游 API 取消,现在都能统一成一条取消路径,resolver 通过
info.getAbortSignal()访问。如果在产生部分数据之后被中止,AbortedGraphQLExecutionError会同时暴露中止原因和部分结果。 - 通过 Node.js 的
diagnostics_channel,解析、校验、执行、字段解析等生命周期事件会被发布出来。APM 埋点不用再猴子补丁(monkey-patch)就能实现。 GraphQLHarness提供了一种官方方式,可以替换 parse/validate/execute/subscribe 各个阶段。公告本身也提到,这遵循的是 Envelop 已经验证过的分阶段模型 — 是社区模式反向输入到参考实现的一个例子。- 面向框架作者,执行流水线更底层的边界(
validateExecutionArgs()、executeRootSelectionSet()等)被公开了出来,可以不复制内部代码就搭建自定义执行器。
也就是说,v17 真正的分量不在 defer/stream,而在服务端运维层面 — 取消、埋点、扩展点。
联邦标准化的现状 — Composite Schemas 处于 Stage 0
这是给所有在等待「联邦 GraphQL 标准化」的人的一次现状盘点。前文提到的 Apollo Federation 归根结底只是一家厂商的规范,而 GraphQL Foundation 从 2024 年 5 月起,就在 Composite Schemas 工作组 里打造一个厂商中立的标准。
截至 2026 年 7 月的老实现状是: 规范仓库 的 README 依然写着 Stage 0(Preliminary) — 处于 Draft 阶段之前,内容仍可能变化。GitHub 发布次数是 0。不过,这绝不是一个死掉的项目 — 2026 年 7 月 9 日还合并了好几个打磨 @key、@require 规则的提交,而在 2026 年 5 月的 GraphQLConf 主题演讲上,The Guild 的 Uri Goldshtein 认为联邦已经不再是前沿实验,而成了一条业界能放心走的成熟道路。从实务角度得出的结论是: 如果你现在要设计联邦架构,依然应该选厂商规范(Apollo Federation v2 系列),Composite Schemas 只需要当作「未来某天可能切换的方向」来关注就够了。
治理层面还有一处变化值得记录。2026 年 6 月发布的 GAPs(GraphQL Auxiliary Proposals) 是一个官方仓库,专门收集核心规范刻意不涉及的惯例 — 比如分页连接(pagination connection)、@cost 这类东西 — 把它们整理成社区规范。核心规范保持精简,周边惯例交给 GAPs,分布式执行交给 Composite Schemas — 标准化正在分化成三层。顺带一提,同一时期 Meta 在 GraphQLConf 2026 主题演讲(「The Creator's Curse」)上反思,十年前「易学易用」的承诺,在数千名工程师的规模下并没有完全兑现,并谈到了内部的重新设计;而 Apollo CEO Matt DeBergalis 则宣称「GraphQL can and must be the language of AI」。标准处于整理模式,厂商讲的是 AI 叙事 — 这是一个存在温差的时间点。
那么现在该做什么
归纳成判断标准如下。
明确该升级到 v17 的情况
- 你在构建服务端框架、网关或埋点工具 — 执行边界 API、Harness、
diagnostics_channel本身就是目的所在。 - 请求取消是你服务里的一个真实问题 — v16 里没有干净的 AbortSignal 集成替代方案。
- 新项目 — 现在 v17 已经是 latest,文档和 API 参考也都按 v17 重新编排了。
不必着急的情况
- 环境被锁定在 Node 22 以下。引擎版本要求是一道硬性门槛。
- 代码库里有大量依赖深层导入或内部 API 的自定义代码 —
exports强制加上执行器分离,会让需要修的地方变多。 - 16.x 不是被抛弃的分支 — 2026 年 6 月还发布了 16.14.2 补丁。如果眼下并不缺功能,先确认周边库的
peerDependencies是否接受 17,再动手也不迟。
对 defer/stream 要更保守一些
- 如果是新引入: 规范还停留在 RFC 2,v17 里函数名也刻着 experimental。payload 格式在 alpha 阶段已经被推倒重来过一次,这就是最好的警示。在确认网关、客户端、缓存全链路都支持同一种格式之前,不要打开它。
- 如果已经在用 alpha 格式跑生产:
legacyExecuteIncrementally()能帮你争取时间,但最好现在就制定迁移到新的 pending/completed 格式的计划。
再补充一点,从 schema 设计的角度看,眼下能白拿的是 @oneOf。如果你手里有「按几个键之一查询」这种模式的输入类型,把 resolver 里的校验代码搬进 schema 声明,这个重构风险很低,客户端类型生成的质量也会立刻变好。当然,这也得先确认服务端和客户端库是否实现了 September 2025 版本 — 规范发布和生态实现之间,总是存在时间差。
结语
总结一下。GraphQL 标准打破了将近四年的沉默,以 September 2025 版本回归,内容偏实务型 — 一致性债务的清偿加上 OneOf 和 Schema Coordinates — 而不是一场华丽新功能的展示。参考实现 GraphQL.js 17 在四年 alpha 之后以 GA 形式发布,在代码层面划清了稳定执行和实验功能(defer/stream、错误传播控制)之间的边界。与此同时,defer/stream 已经在规范之外待了十年,联邦标准(Composite Schemas)仍处于 Stage 0。
这幅图景也可以冷嘲着读 — 「花了四年就搞出这个?」但反过来读,对实务更有用。这个项目选择的是宁愿等十年,也不把破坏性变更塞进规范里,所以按 October 2021 规范搭建的服务端,到今天依然有效。稳定是默认值,实验则自带标签而来 — 这是值得对 API 层的基础技术抱有的期待。对照同一时期 Protobuf 通过 Edition 体系收紧默认值的方式来看,能看出两个阵营都在向「管理迁移成本,而非追逐创新」收敛。与其把时间花在为标准的速度感到失望,不如先着手做 @oneOf 重构和 v17 升级的估算。
参考资料
- GraphQL Specification Versions — spec.graphql.org
- September 2025 版本全文
- Announcing the September 2025 Edition of the GraphQL Specification — graphql.org 博客
- September 2025 官方变更日志 — graphql/graphql-spec
- Introducing GraphQL.js v17 — graphql.org 博客
- GraphQL.js v16→v17 官方升级指南
- GraphQL.js Defer/Stream 文档
- GraphQL RFC 追踪器 — Incremental Delivery 等进展状态
- graphql/composite-schemas-spec 仓库 (Stage 0)
- Announcing the Composite Schemas Working Group (2024-05)
- Introducing GAPs: GraphQL Auxiliary Proposals (2026-06)
- GraphQLConf 2026 wrap-up (2026-07-14)
- What Launched at GraphQLConf 2025 — Meta 提及 @async
- graphql 包的 npm 注册表 (版本、日期原始来源)
현재 단락 (1/99)
GraphQL 规范的最后一个版本,长期以来一直停在 [October 2021](https://spec.graphql.org/)。在此期间生态系统一直在往前走 — [Apollo Federa...