GraphQL CheetSheet

0x00 前言

不定期更新。

0x01 开接口这件小事情

开接口,究竟什么样的接口才是一个好接口?

  1. 刚开始的时候,后台开接口都是比较随便,本着方便,快速的方式一个一个接口的开。
  2. 后来呢?觉得接口开出来没有最佳实践,所以有人提出 Restful 的开接口姿势。 Swagger, DjangorestFramework, 以及 Apistar 便是这种最佳实践的代表性项目
  3. 再后来呢?Facebook 又搞了套自己的开接口姿势叫做 GraphQL, graphene-python , graphene-js , apollo-client , apollo-server 便是这种最佳实践的代表性项目

开接口注意点

  1. 尽量做到代码即文档。
  2. 便于前端调试。
  3. 分页处理。
  4. API 版本管理。
  5. 额外的语义。
  6. 校验。
  7. 权限。

不管是 Restful 的实现,还是 GraphQL 的实现,在 1/2/5 上面做的非常优秀了。

拿 Restful 的实现 DjangoRestframework 来说,直接可以在 ApiView 的注释里面写 Markdown 语法,兼容 payload 和 form 表单调试。内置 Serializer 进行序列化和校验。

DRF 还是一个功能非常全面的框架。 PS: 如果你是不折腾的 Django 用户,DRF 绝对让你欲罢不能。

开接口不能解决的问题

业务逻辑的沟通问题

抛开前后端分离所带来的优点,前后端分离的一大问题就是,前后端人员的分离。

如果你的公司规模不是很大,开发的项目需要一定的背景知识,团队开发比较(经常)敏(调整)捷(需求), 沟通上就会有些问题,

具体表现为,后端理解了需求,还需要和前端讲清楚,而刚讲清楚没几天,产品又跑过来说,这个业务我们需要调整一下。几次折腾下来,就会出现一个尴尬的局面。

前后端有的时候对业务理解出现来偏差。在以前不区分前后端的时候,一个东西到实现基本上一个人就可以 Cover 掉,只要这个人理解了业务逻辑,就行了。现在前后端分离,就要求前后端对需求的理解

如果需求不明确,就会出现如下情况,前端一脸懵逼的问后端与产品『眼前的黑不是黑,你说的白是什么白』

当然,这个不属于技术问题,只是提一下。

0x02 GraphQL 相关概念

GraphQL 是什么?

GraphQL 也不是什么革命性的产品,不过是一种新的开 Web 接口的方式罢了。

而请求接口提交的参数也变成了包含参数的一种查询语言。

官方宣传的 GraphQL 搞好了,只需如此:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
# Step1. 描述你的数据
type Project {
name: String
tagline: String
contributors: [User]
}
# Step2. 请求所需数据。
{
project(name: "GraphQL") {
tagline
}
}
# Step3. 拿到所需数据。
{
"project": {
"tagline": "A query language for APIs"
}
}

嗯,是不是和 SQL 看起来有点像?当然咯,都是查询语言 (QL) 嘛。

GraphQL 好处

GraphQL 的好处,自然是前端写起来就是一个字,爽。

比如我们使用 Github 的 API 做一个简单的查询

地址如下 https://developer.github.com/v4/explorer/

查询如下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
query {
viewer {
login
bio
repositories(first:10, orderBy : { field: STARGAZERS, direction: DESC} ) {
nodes {
nameWithOwner
viewerHasStarred
watchers {
totalCount
}
stargazers {
totalCount
}
}
totalCount
}
}
}

结果如下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
{
"data": {
"viewer": {
"login": "twocucao",
"bio": "Pythonist In Shanghai.",
"repositories": {
"nodes": [
{
"nameWithOwner": "twocucao/danmu.fm",
"viewerHasStarred": true,
"watchers": {
"totalCount": 22
},
"stargazers": {
"totalCount": 282
}
},
{
"nameWithOwner": "twocucao/YaDjangoBlog",
"viewerHasStarred": true,
"watchers": {
"totalCount": 9
},
"stargazers": {
"totalCount": 120
}
},
{
"nameWithOwner": "twocucao/danmu",
"viewerHasStarred": true,
"watchers": {
"totalCount": 5
},
"stargazers": {
"totalCount": 64
}
}
],
"totalCount": 33
}
}
}
}

如果你说,我还要看看这个 repo 的主要语言,那么增加一行查询即可。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
query {
viewer {
login
bio
repositories(first:3, orderBy : { field: STARGAZERS, direction: DESC} ) {
nodes {
nameWithOwner
viewerHasStarred
languages(first: 3) { # 在这里增加查询编程语言
nodes {
name
}
}
watchers {
totalCount
}
stargazers {
totalCount
}
}
totalCount
}
}
}

依照这个简单的查询,可以看出 GraphQL 的便捷之处。后端编写完毕之后,前端基本上就可以对着 Schemas 里面的 query 查询完毕了。

查询这么搞可以,增删改查之类的操作呢?GraphQL 里面还有 Mutation 可以帮你解决这个问题,在后端定义完 Mutation , 前端在 Mutation 里面可以直接传参。

就像这样。

0x03 GraphQL 客户端怎么做?

0x04 GraphQL Python 服务端怎么做?

0x05 GraphQL 解决的痛点与坑

0x06 其他思考点

  • 埋点

0xEE 参考链接


ChangeLog:

  • 2017-01-20 初始化本文