LabHub

博客

GraphQL 规范,时隔近 4 年的发布 — September 2025 版本与 GraphQL.js 17 GA 里都有什么,还差什么

한국어English日本語中文

引言 — 一个看似停滞的标准动了起来

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 支持

总的来看,这次版本不是新功能的盛宴,而是四年积压的一致性债务清偿,外加两项分量十足的语言特性(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 — 什么会坏,什么会变好

官方升级指南 写得异常详尽,这里只挑出做判断所需的要点。

会坏的部分

执行器分离 — 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 的格式用 pathlabel 来标识 payload,字段数据可能重复;现在的格式则是把 pending 项用 id 登记,再用 completed 通知完成。为了需要旧格式的宿主,legacyExecuteIncrementally() 被保留了下来,但正如名字所说,它是过渡期用的。这就是提前用规范外功能要付的账单的一个实例。

错误传播这一侧也进来了一项实验功能。给某个操作加上 @experimental_disableErrorPropagation,non-null 字段的执行错误就不会连锁地把父级也变成 null,而只让该位置本身变成 null — 这瞄准的是使用规范化缓存的客户端里,祖先节点变 null 容易被误认成真实数据更新的问题,是正在讨论中的错误行为(onError)规范议题的先行实现。这个功能同样在名字里刻着 experimental。

对运维有用的部分 — AbortSignal、diagnostics_channel、Harness

除了会坏的东西,能得到的收获也是实打实的。

也就是说,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 的情况

不必着急的情况

对 defer/stream 要更保守一些

再补充一点,从 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 升级的估算。

参考资料

评论

还没有评论。

登录后即可发表评论