GraphQL 简介以及如何使用 GraphQL API

2025-06-10

GraphQL 简介以及如何使用 GraphQL API

过去一年,我一直在广泛使用 Contentful GraphQL API 在 Jamstack 上构建各种项目,虽然对 GraphQL 的内部工作原理知之甚少,但我很快就沉迷其中。虽然只需稍加研究就能轻松上手使用 GraphQL 进行第一个查询,但我认为整合我一年来所学的知识,并为所有有兴趣入门的人提供一份 GraphQL 的高级介绍,会很有帮助。

什么是 API?

API 代表应用程序编程接口 (API),是不同软件服务之间进行通信的一种方式。不同类型的 API 用于硬件和软件编程,包括 Web API——例如 Contentful 提供的 API。如果您是开发新手,我建议您阅读这篇博文——什么是 API? ——以深入了解 API 及其在 Web 开发中的作用。

GraphQL 简史

GraphQL 是一种用于与后端系统通信的语言,允许您获取和操作数据。它由 Facebook 于 2012 年开发,并于 2015 年向公众发布。2019 年,该项目被移交给非营利组织GraphQL 基金会,其使命是确保 GraphQL 社区能够专注于在中立平台上的持续发展。

GraphQL 是什么意思?

GraphQL 与语言无关,这意味着它可以与任何后端框架或编程语言一起使用,并且本质上是后端服务的补充,允许开发人员以特定方式与数据库通信并请求数据。

要为您的数据源创建 GraphQL 服务器,您可以使用专门的工具(例如ApolloGraphQL),它允许您在后端和数据库之上创建一个层,从而能够通过图形查询语言来表示、查询和更改您的数据。

最后,GraphQL 代表“图查询语言”。让我们来解释一下“图”和“查询语言”的含义。

您的数据以图表形式呈现

GraphQL 会创建一种数据表示形式,旨在使其感觉熟悉且自然,就像一个可视化的图表。《牛津学习词典》将图表定义为:

[由一条或多条线组成的图表,显示两组或多组数字之间的关系。

GraphQL 的图 (Graph) 部分描述了一组对象(或节点)的数据结构,这些对象通过一组链接(或边)相互连接。通过这种图结构,可以在用户界面中呈现不同对象之间的关系。其关键概念在于,这种数据结构是非线性的,这意味着一个对象可以连接到多个其他对象,并且关系也可以是循环的。

有一些专门的工具,例如GraphiQL,可以用来表示 GraphQL API 上节点类型之间的关系。以下是另一个优秀工具的截图——Contentful应用市场中的 GraphQL Playground 应用——展示了支持我个人网站的 Contentful 空间中数据之间的关系。请注意,您可以深入研究每种内容类型中的数据类型,并了解它们之间的关系。

这是 Contentful 中 GraphQL 演练环境的屏幕截图,其中显示了文档选项卡的打开状态,以及 GraphQL 模式中对象或节点之间的连接。在这个特定的示例中,blogPost 节点包含一个 author 节点,该 author 节点包含一个 image 节点,该 image 节点包含一个 String 类型的 fileName。

在这个特定的例子中,一个blogPost节点包含一个author节点,该节点包含一个image节点,该节点包含一个String 类型的fileName对象。沿着突出显示的节点,沿着树向下追踪关系。

能够检查数据中存在的所有类型是一个非常强大的工具,其结果可预测,可帮助您构建健壮且可扩展的应用程序。如果您是一名前端开发人员,您可能已经开始意识到,在用户界面中拥有对内容数据结构的这种可见性和洞察力,将会让您感觉非常强大!如果您想了解更多关于“图思维”的信息,请查看graphql.org 提供的精彩资源

这就是GraphQL 的部分。接下来,我们来看看查询语言以及类型系统如何将所有内容联系在一起。

类型系统使事情变得可预测

您可能已经熟悉 REST API 的概念,它采用基于资源的方法进行数据读写,具体方法取决于 HTTP 上 API URL 的格式。(如果您不熟悉 REST,并且想要了解更多背景信息,请参阅这篇文章 —什么是 REST API?)与 REST 不同,GraphQL 查询语言允许您通过一次 API 调用,使用单个 URL 端点(通常通过 HTTP)从多个不同的“资源”(例如博客文章、页面、作者等等)请求数据。

构建网页时,您可能需要在不同的 UI 组件中显示不同类型的数据。您可能需要获取博客文章、作者、导航链接、相关博客文章列表等等——所有这些都在单个页面上。使用 GraphQL,您可以在一个 API 调用中请求构建 UI 所需的所有不同类型的数据,而不必对不同的“资源”发出多个请求。

下面是一个 GraphQL 查询的示例,它从 Contentful 中的四种不同内容类型(或资源)请求数据: a blogPost、 an author、 anevent和 a talk。本质上,我们请求四个不同的对象,以及这些对象上的特定字段。例如,对于eventCollection对象,我们请求items字段;对于 中的每个对象items,我们请求 字段name。查询以单词 query 为前缀——在 GraphQL 模式中,查询的类型为Query! 。

使用 REST API 时,您需要进行四次不同的 API 调用来请求这四种不同类型的数据。使用 GraphQL,您可以一次性完成所有操作!

query {
  blogPostCollection {
    items {
      title
      author {
        name
      }
    }
  }
  eventCollection {
    items {
      name
    }
  }
  talkCollection {
    items {
      title
    }
  }
}
Enter fullscreen mode Exit fullscreen mode

这是查询的结果。请注意,我们请求的所有数据都包含在一个响应中。(注:为了能够在单个页面视图中演示这一点,我在下面的查询中添加了限制。)GraphQL 响应对象的另一个优点是,返回的对象键与我们请求的完全相同。这使得 GraphQL 的使用更加可预测且直观。您将在响应中获得与您请求的内容完全相同的内容——不多不少——并且顺序和结构完全相同。

Contentful 中的 GraphQL 游乐场的屏幕截图,显示了上述查询的结果。

在 GraphQL 资源管理器中构建查询时,使用键盘快捷键ctrl + 空格键可以查看对象上可选的字段。这是一种便捷的方法,可以在构建查询时获取有关数据架构以及这些字段的数据类型的内联提示。

带注释的图表展示了按下 Ctrl 键和空格键时 GraphQL 资源管理器中显示的提示或上下文菜单。该菜单显示了当前节点上可查询的字段,以及选中该字段时字段的类型。

如果您想深入了解 GraphQL 中的类型,请查看有关模式和类型的官方 GraphQL 文档

你可能会想——这个图结构是如何从 GraphQL 模式生成的?让我们来看看自省查询。

自省查询公开了 GraphQL 模式

GraphQL 自带自省查询系统,它能够查询数据库中的类型系统和数据结构,以便生成文档并在 GraphQL UI 中提供提示。如果您不熟悉“自省”这个词,它的意思是审视自身并检查自身的状态。

您实际上可以使用 GraphQL 本身来查询您的 GraphQL 架构!此根级查询将返回架构中拥有的所有数据类型。

query {
  __schema {
    types {
      name
    }
  }
}
Enter fullscreen mode Exit fullscreen mode

GraphQL 游乐场的屏幕截图显示了上面进行的模式查询的结果。

您将看到自省查询中返回的三种不同类型的数据。

  1. 由模式定义的类型:就我用 Contentful 构建个人网站而言,这些类型将是诸如BlogPost、、、等等AssetTalkEventProject
  2. 由字段数据类型(标量类型)定义的类型:如StringBoolean
  3. 内部自省查询类型:例如__Schema,,__Type__Field并且这些都以双下划线为前缀。

在 GraphQL 中,查询中的每个字段都充当一个函数,它会依次返回下一个字段类型、下一个类型、下一个类型,直到返回的字段为标量值,例如字符串或布尔值。上面我的个人网站上的示例演示了这一点,其中一个blogPost节点包含一个author节点,该节点包含另一个image节点,该节点包含一个字符串类型的fileName量值,至此,整个过程就结束了。

执行任何字段时,都会调用解析器来生成字段值。在开发您自己的 GraphQL 服务器并进行数据库更改时,您需要为添加到 API 的每个新字段类型提供一个解析器。从 GraphQL.org 了解更多关于解析器的信息

Contentful GraphQL API 的一个强大功能是,数据的 GraphQL 模式在请求时生成,这意味着它始终与 Contentful 空间的当前状态保持同步。您无需担心解析器——我们为您处理。

如果您想了解有关内省查询的更多信息,以及如何在加载 GraphQL 资源管理器时在浏览器的网络选项卡中观看它们的运行,请查看 Contentful Youtube 频道上的此视频

到目前为止,我们只关注从 GraphQL API 读取数据。但是,通过 GraphQL 写入数据库也是可能的——这伴随着另一个特殊的词——突变 (mutation)

使用 GraphQL 突变写入数据

变异 (Mutate) 指的是改变或操作某物。您可以使用 GraphQLmutation查询前缀的关键字来操作服务器端数据。Contentful GraphQL API 是只读的,因此您无法使用 GraphQL 在 Contentful 中执行变异操作。但理论上,如果我想创建一篇新的博客文章,保存标题,并在响应中返回新数据,其工作原理如下。

mutation CreateNewBlogPost($title: String!) {
  createBlogPost(title: $title) {
    title
  }
}
Enter fullscreen mode Exit fullscreen mode
  • 查询以单词 开头mutation,在支持变异的 GraphQL API 中,它的类型是Mutation,就像上面描述的读取查询的类型一样Query
  • 接下来,我们需要将突变封装在一个类似函数的函数中,并在其中定义完成突变所需的变量及其类型。CreateNewBlogPost 函数接受一个 String 类型的变量 title。“!”表示该变量是突变发生的必需变量。有关如何在 GraphQL 中使用变量的更多信息,请参阅我之前写的这篇博文:
  • 在“函数”内部,您可以使用 GraphQL API 上提供的突变(使用自省查询来找到它!)。在本例中,它是createBlogPost。在突变内部,定义要传入的变量。
  • 最后,在突变中,定义您希望在响应中返回的字段。在本例中,我只是创建一个标题,所以我只想在响应中返回新的标题。

使用变更查询和变量向 API 发出请求,以下是变更完成后 API 的响应。同样,输出与输入的格式一致,易于识别!

{
  "data": {
    "createBlogPost": {
      "title": "My new blog post title!",
    }
  }
}
Enter fullscreen mode Exit fullscreen mode

要了解有关 GraphQL 突变的更多信息,请查看 GraphQL.org 的官方文档

现在我们已经介绍了如何在支持的情况下从 GraphQL API 读取(查询)和写入(变异),让我们简单了解一下如何与 GraphQL API 通信来执行这些操作。

如何与 GraphQL API 进行通信

GraphQL 通常通过 GraphQL 服务器通过 HTTP 协议提供服务。虽然还有其他方式与 GraphQL 通信,例如通过 WebSocket,但 HTTP 协议仍然是最流行的选择。如果您想了解如何通过 HTTP 将 GraphQL 与 cURL、Python、JavaScript、Ruby 和 PHP 结合使用,请查看这篇博文:通过 HTTP 协议使用 GraphQL 的五种方式

以下是一个简单的示例,说明如何使用 JavaScript fetch 通过 GraphQL 从存储在 Contentful 中的博客文章中请求标题和摘录。您可以使用任何支持 HTTP 的语言或框架进行相同的 HTTP 调用!

在此示例中,我们通过 HTTP POST 发送请求,在 Authorization 标头中发送访问令牌,并在请求正文中发送 GraphQL 查询。您也可以通过 HTTP GET 发出相同的请求,但需要将查询和访问令牌附加到请求的 URL 中。请参阅文档,了解更多关于在 Contentful GraphQL API 上使用 HTTP POST 和 GET 的信息

// Build the GraphQL Query
const query = `{
  blogPostCollection(limit: 1) {
    items {
      title
      excerpt
    }
  }`;

// Send a POST request via fetch to the Contentful GraphQL URL endpoint
const response = await fetch("https://graphql.contentful.com/content/v1/spaces/{yourSpaceId}", {
  method: "POST",
  // Include Authorization and Content-Type HTTP headers
  headers: {
    Authorization: "Bearer {yourAccessToken}",
    "Content-Type": "application/json",
  },
  // Send the GraphQL query in the body of the request
  body: JSON.stringify({ query }),
}).then((response) => console.log(response.json()));
Enter fullscreen mode Exit fullscreen mode

嘭!你从 GraphQL API 中获取了数据!记住,GraphQL 与语言无关,因此你可以使用任何编程语言或框架读取和写入 GraphQL API——只要它支持你需要的协议,例如 HTTP。

进一步阅读

GraphQL 是一种强大的工具,可以组织您与后端服务和数据库的通信方式。今年我非常享受探索 GraphQL 的各种可能性,并且非常期待深入研究新的项目。我甚至可能会尝试构建自己的 GraphQL API!

要了解更多关于使用 GraphQL 获取 Contentful 数据(包括已发布和预览内容)的信息,请查看官方文档。如果您想更深入地探索 GraphQL 的精彩世界,请查看graphql.org上的官方 GraphQL 规范和学习资料。或许这会激发您构建自己的 GraphQL API 的灵感。祝您查询愉快!

鏂囩珷鏉ユ簮锛�https://dev.to/whitep4nth3r/an-introduction-to-graphql-and-how-to-use-graphql-apis-13i
PREV
HTML 就是创建网站所需的一切
NEXT
构建 TailwindCSS 类名的简单策略