前端 GraphQL 入门

本文翻译自 https://css-tricks.com/front-end-developers-guide-graphql/ , 作者 PEGGY RAYZIS,翻译:Thomas Chan

不管项目的大小,你肯定会向服务器请求数据的。这么多年来,REST API 的现状通常是前端需要发出请求,解析返回结果,然后更新界面。
不过去年诞生了一个新的 API 技术 GraphQL,因为更优异的开发者体验以及用陈述性的方式获取数据而倍受欢迎。

接下来我们动手写几个示例,了解 GraphQL 将如何解决你的项目中对获取数据的痛。如果你刚知道 GraphQL,别慌!我在文中加了链接,可以帮助你学习 GraphQL

GraphQL 101

当我们在说 GraphQL 时,要么是说语言本身,要么是说围绕的生态系统。GraphQL 核心是 Facebook 开发的一种查询语言,允许你用陈述性语句描述你想要的数据。返回结果的数据结构就是你所描述的数据结构:看下面的例子,我们希望服务器返回一个 Object,有一个 currency 属性,一个 rates 属性,rates 是一个包含 currency 和 rate 组成的 object 的数组。

{
  rates(currency: "USD") {
    currency
    rates {
      currency
      rate
    }
  }
}

广义上的 GraphQL 是说所围绕的生态系统、工具链。后端用 Apollo Server 创建一个 GraphQL 服务,接收、解析并返回数据。用 GraphQL Tools 建 schema、映射数据结构。

这些看起来都还挺复杂的,其实很简单 — 使用 Apollo Launchpad 以及不到 60 行代码就可以创建一个可玩的 GraphQL 服务!我们接下来会使用我 事先创建好的 Launchpad(包含了 Coinbase 的 API)。

上手 GraphQL

现在你知道 GraphQL 是啥了,我们开始动手练习几个小示例,了解如何使用 Apollo 进行前端开发。

1. 不再怕产品经理改需求

我们之前都有过这样的经历:你花了好几个小时写好了页面,突然产品需求改了,你想了想要实现新的需求,现有的 API 流程都得改,甚至还得加新的 API。然后你告诉后端要新加一个只为一个组件用的 API。

使用 GraphQL 的话这些问题都不存在,因为你要的数据都不再由相应的 API 组合后给你,你将会只请求一个地址。GraphQL 服务通过 schema 列出所有可用资源,你就可以自由组织想要的查询结果数据结构。来用 我们的 Launchpad 演示一下:

在 schema 里的第 22-26 行我们定义了一个 ExchangeRate 类型,这些字段列出了所有我们可以查询的资源。

type ExchangeRate {
  currency: String
  rate: String
  name: String
}

用 REST API 其实限制了对资源的获取,比如你有一个 API是 /exchange-rates,但是返回结果里没有包含 name,此时你要么修改接口要么新增一个 API /currency

而用 GraphQL,通过 schema 我们知道 name 是可以一起查询的,所以可以在原有查询的基础上直接加上 name,在我们的 Launchpad 里试试运行下面的例子!

{
  rates(currency: "USD") {
    currency
    rates {
      currency
      rate
      name
    }
  }
}

你把 name 参数去掉,再请求一次,看看返回的结果有什么不同?

result diff

GraphQL 相比 REST API 有一个明显的区别,GraphQL 只会返回给你你所请求的数据及数据格式,不像 REST API 的返回结果,你总是需要对结果进过过滤、转换等操作以符合界面所需要的格式。这不仅节省了前后端制定、联调 API 的时间,还缩减了网络请求包的大小,CPU 的占用率(接收、解析网络请求)。

2. 减少你对数据的状态管理

请求数据总是意味着要更新界面。典型场景是你的代码至少有三个判断:请求中、请求成功、请求错误。请求成功后你要把数据转成界面需要的格式,可能会需要做缓存,然后更新界面。这个流程在项目里会重复多次,会有很多重复性的类似代码、模板。

我们来通过这个 CodeSandbox 的 React 例子(链接里点击list.js,滚动到最下边)看一下 Apollo 客户端是如何优化这个重复性的流程的。

export default graphql(ExchangeRateQuery, {
  props: ({ data }) => {
    if (data.loading) {
      return { loading: data.loading };
    }
    if (data.error) {
      return { error: data.error };
    }
    return {
      loading: false,
      rates: data.rates.rates
    };
  }
})(ExchangeRateList)

这个例子是 Apollo 客户端的 React 版本,将 exchange rate 请求绑定到了 ExchangeRateList 组件上,当 Apollo 客户端发起请求自动判断请求状态并且把状态赋值给 data 参数。当 Apollo 客户端接收到数据就会把数据更新到 data 参数上,React ExchangeRateList 组件就会更新了。

背后的 Apollo 客户端帮你解析并缓存了数据。你可以试试在右边栏点击货币看看数据的刷新,快速的一秒点击一个,注意看数据是不是立即更新的?那就是 Apollo 客户端的缓存了!你可以直接使用 Apollo 客户端,无需额外配置,可以看看 index.js 里是如何初始化 Apollo 客户端的。

3. Apollo DevTools & GraphiQL

Apollo 客户端帮你做了很多事!不如我们深入看看到底干了啥?Apollo DevTools 不仅能查看整个 store 及每次查询的数据、状态,还能是 debug 更容易!你可以在 Chrome 和 Firefox 的应用商店里找到 Apollo DevTools,React Native 的很快就会有。

如果你想试试,你可以把 Apollo DevTools 装在你常用的浏览器上。你可以尝试本地运行一下,访问上文那个 CodeSandbox 的例子,点击导航栏里的 Download,解压文件,运行 npm install,然后 npm start,打开浏览器的开发者工具,在 tab 栏里你会看到 Apollo。

首先我们看下 store 查看器,这个 tab 映射了当前 Apollo 客户端的数据,在这里你可以确认数据是不是正确。store

GraphiQL 是一个交互式查询编辑器,还提供了文档浏览功能。Apollo DevTools 还可以配合 GraphiQL 一起测试数据查询,其实在上文的第一个例子里你已经用过了。GraphiQL 会根据你的查询自动生成 GraphQL 格式的文档,对开发者来说非常有用。

GraphQL query result

你可以在 我们的 Launchpad 的右边栏里执行 GraphiQL 的查询,在编辑器里把鼠标放在字段上就可以查看文档。

深入 GraphQL

看到这里你可以为自己鼓鼓掌了!希望上边的练手例子能帮助到你了解在前端如何使用 GraphQL 。

想了解更多?把学习 GraphQL 加入到你的 2018 年学习计划吧!不出我所料的话明年 GraphQL 会更火,下边的链接是你可以尝试玩玩的例子,知识点我们今天都了解了。

开始使用 GraphQL 吧(别忘了在 Twitter 上 follow 我们呀 @apollographql)!