🙅♀️ 为什么 GraphQL 不应该纳入 WordPress 核心
更新 01/05/2024: 查看 Gato GraphQL vs WP REST API 对比。
是的,您没有看错这个标题。尽管我本人就是 WordPress GraphQL 服务器的作者,但我已经改变了对 WordPress 是否应该内置 GraphQL 的看法。
不久前,我还相信 GraphQL 应该纳入 WordPress 核心。理由是贡献者们正在花费时间和精力为 WP REST API 实现批量操作等功能,而这些功能本就是 GraphQL 的原生特性。
然而,最近我了解到一些新的信息,促使我重新思考。现在我认为,由于额外引入的风险,WordPress 不应该内置 GraphQL。

以下是我的理由。
1. 不满足 80/20 法则
从历史上看,某项功能被添加到 WordPress 核心,仅当它满足 80/20 法则,即 80% 或以上的用户会使用它。
GraphQL 是否符合这一条件?基于 WP REST API 引入 WordPress 4.7 的先例,我认为答案是"否"。
K. Adam White(WP REST API 初期开发和发布的主要负责人)在其演讲 WordPress as Data, 5 Years In 中描述道,贡献者们曾期望 REST API 随核心发布后会被广泛使用。但这并未发生:开发者们继续以原有方式构建 WordPress 站点,对"无头"模式或 REST API 几乎不感兴趣。
局面直到后来才发生转变——WordPress 5.0 引入了基于 REST API 的 Gutenberg 编辑器。那么,Gutenberg 能否为将 GraphQL 加入 WordPress 核心提供依据?

2. 无头模式已通过 REST API 得到满足
WordPress 编辑器可以通过原生 GraphQL 服务器进行增强,让区块开发者能够使用 GraphQL(在现有 REST API 之外)来为其区块获取数据。此外,主题和插件也可以利用 GraphQL 驱动各自的内部功能。这些都是将 GraphQL 添加到 WordPress 核心的有力理由。
然而,WordPress 已经拥有 REST API,而 GraphQL 能做的事情 REST 同样可以做到。在 REST 之外再引入 GraphQL,就像已经开着丰田却还要买一辆宝马。你会更快到达目的地,驾驶体验也会更出色。但两辆车都能带你去想去的地方。
由于 GraphQL 并不提供此前无法实现的功能,其纳入核心并不完全合理。GraphQL 确实能提升与 API 交互的体验,但这完全可以归入插件领域。

3. WordPress 主题和插件可以使用 webonyx/graphql-php
公开插件无法要求网站安装 WPGraphQL 或 Gato GraphQL 才能使用该插件,因为这会降低其潜在覆盖范围。因此,公开插件无法依赖 GraphQL,这实在令人遗憾。
我对此深入思考,并提出了一个潜在解决方案:GraphQL API Private——一个插件可以为自身使用而嵌入的自包含 GraphQL 引擎,以 Composer 包的形式分发。(我尚未开始这个项目的工作。)
然而就在几周后,一个基于 GraphQL 的 WordPress 插件发布了。我很好奇作者是如何实现的:是在底层使用了 WPGraphQL 还是 Gato GraphQL?于是我查看了其源代码,结果发现,它直接使用了 webonyx/graphql-php!
这是一个有趣的解决方案,证明只需一些努力,开发者目前就可以在主题和插件中使用 GraphQL。
该插件使用 GraphQL 来获取自身的数据实体,而非 WordPress 的数据实体(文章、用户、评论等)。因此,它不需要像 WPGraphQL 和 Gato GraphQL(以及最终的 GraphQL API Private)那样重建包含 WordPress 数据模型的 GraphQL schema。在这种情况下,依赖 webonyx/graphql-php 是合理的。

4. GraphQL 带来额外风险
以上三点表明,GraphQL 能够增强 WordPress,尽管其说服力并不十分突出。从这个角度来看,我们仍然可以将 GraphQL 添加到 WordPress 核心,要么从中受益,要么什么都不发生。
但第四点表明,如果 GraphQL 对 WordPress 增益有限,那么由于其额外引入的风险,就不应该添加。
GraphQL 容易受到以下攻击向量的威胁(其中包括):
- 单一端点提供对网站所有信息的访问,因此可能无意间暴露私密数据。
- Query 可能非常复杂,可能使 Web 服务器和数据库服务器不堪重负。
- 同一个 mutation 可以在单个 Query 中执行多次,多个 Query 也可以在单个请求中一起执行,使攻击者能够尝试大量用户名/密码组合来获取后端访问权限。
这些攻击的危害可能极为严重。网络安全研究员 Dolev Farhi 在其演讲 Damn GraphQL - Defending and Attacking APIs 中,通过向 WPGraphQL 端点发送一批复杂 Query,在不到 30 秒内就成功使一个 WordPress 站点宕机。
WPGraphQL 团队立即修复了这一问题。但我们如何确保不会出现其他漏洞利用?(我不仅指 WPGraphQL,也包括 Gato GraphQL。)
这些攻击在 GraphQL 中可能发生,而在 REST 中不会,因为 GraphQL 比 REST 更强大。在 REST 中,Query 是预先定义并存储在服务器端的;而在 GraphQL 中(除非使用 persisted queries),Query 是在运行时由客户端提供的。
如果网站管理员在配置谁可以访问端点或哪些数据会被暴露时疏于管理,就可能发生问题。考虑到 WordPress 的普及程度——数百万非技术用户在使用它——问题很可能会真实发生。

总结
请注意:我并非主张不在 WordPress 中使用 GraphQL(当然不是!),而是主张负责任地使用 GraphQL。GraphQL 功能强大,这意味着它也具有一定危险性。使用 GraphQL 时,我们需要确保自己清楚地知道自己在做什么。
将 GraphQL 内置到 WordPress 核心,会将其交到大量用户手中,其中许多人不会意识到其风险,也不会采取适当的防护措施。这是潜在灾难的根源。因此,这是我目前的看法——应该避免这样做。