本文由智能化研发管理工具 PingCode 技术经理 龚林杰分享
什么是 GraphQL
A query language for your APIs
GraphQL 是一种由 Facebook 提出的用于 API 的查询语言,也是一个满足你数据查问的运行时。GraphQL 对你的 API 中的数据提供了一套易于了解的残缺形容,使得客户端可能精确地取得它须要的数据,而且没有任何冗余
罕用的 API 有哪些
什么是 API
API 全称:Application programming interface,API 的实质就是读数据、写数据。
咱们罕用的 API 分成两个流派
- 基于 REST(Representational State Transfer)
REST:体现层状态转移,是一种软件架构格调,而不是一个规范。REST 用 HTTP 封装,走的是 HTTP 协定。那么给予 REST 有哪些衍生品?RESTFUL: 操作资源,GraphQL: A query language for your APIs
- 基于 RPC
用自定义的协定 http, http2, 音讯队列(redis), tcp 等封装的一套近程调用的 API,很典型的一个技术就是 gRPC.
为什么要应用 GraphQL
REST API 存在的问题以及怎么应答
- POST / PUT / DELETE 傻傻分不清楚,有时候界线含糊
- 因为是操作资源路由有时候会很长,如 /work-items/:id/comments/:cid/like
- 数据返回冗余,叫 Overfetching
- 数据返回短少一些字段,叫 Underfetching
- 接口数据如何兼容不同平台
咱们在应用 REST 接口时,接口返回的数据格式、数据类型都是后端事后定义好的,如果返回的数据格式并不是调用者所冀望的,作为前端的咱们能够通过以下两种形式来解决问题:
- 和后端沟通,改接口(更改数据源)
- 本人做一些适配工作(解决数据源)
- 后端专门为其余平台 (挪动端) 提供接口
GraphQL 的劣势在哪
借助 GraphQL,组织内的不同客户端应用程序能够轻松地仅查问所需数据,这一点超过了其它 REST 办法,并带来了理论应用程序性能的进步。应用传统的 REST API 端点,客户端应用程序将详询服务器资源,并承受蕴含了与申请匹配的所有数据的响应。如果来自 REST API 端点的胜利响应返回 35 个字段,那么客户端应用程序就会收到 35 个字段。
- GraphQL API 有强类型 schema
- 按需获取
- GraphQL 反对疾速产品开发
- Composing GraphQL API
- 丰盛的开源生态和社区
GraphQL 的概念和示例
Schema 和 类型 (Schemas and Types)
- 类型零碎(Type System)
GraphQL 查询语言基本上就是对于选择对象上的字段
因为一个 GraphQL 查问的构造和后果十分类似,因而即使不晓得服务器的状况,你也能预测查问会返回什么后果。然而一个对于咱们所须要的数据的确切形容仍然很有意义,咱们能抉择什么字段?服务器会返回哪种对象?这些对象下有哪些字段可用?这便是引入 schema 的起因。
每一个 GraphQL 服务都会定义一套类型,用以形容你可能从那个服务查问到的数据。每当查问到来,服务器就会依据 schema 验证并执行查问。
query {
blogPosts {title}
}
- 类型语言(Type Language)
GraphQL 服务能够用任何语言编写,因为咱们并不依赖于任何特定语言的句法句式来与 GraphQL schema 沟通。咱们定义了本人的简略语言,称之为“GraphQL schema language”—— 它和 GraphQL 的查询语言很类似,让咱们可能和 GraphQL schema 之间能够无语言差别地沟通
- 对象类型和字段(Object Types and Fields)
一个 GraphQL schema 中的最根本的组件是对象类型,它就示意你能够从服务上获取到什么类型的对象,以及这个对象有什么字段。应用 GraphQL schema language,咱们能够这样示意它
- 参数(Arguments)
- 查问和变更类型(The Query and Mutation Types)
schema {
query: Query
mutation: Mutation
}
- 标量类型(Scalar Types)
一个对象类型有本人的名字和字段,而某些时候,这些字段必然会解析到具体数据。这就是标量类型的起源
GraphQL 自带一组默认标量类型:
Int
:有符号 32 位整数。Float
:有符号双精度浮点值。String
:UTF‐8 字符序列。Boolean
:true 或者 false。ID
:ID 标量类型示意一个惟一标识符
- 枚举类型(Enumeration Types)
enum BlogType {
TECH
NEWS
...
}
- 列表和非空(Lists and Non-Null)
对象类型、标量以及枚举是 GraphQL 中你惟一能够定义的类型品种。然而当你在 schema 的其余局部应用这些类型时,或者在你的查问变量申明处应用时,你能够给它们利用额定的类型修饰符来影响这些值的验证
myField: [String!]
query BlogPostWithComment($id: ID!) {blogPost(id: $id) {
title
... on BlogPost {description}
}
}
- 接口(Interfaces)
跟许多类型零碎一样,GraphQL 反对接口。一个接口是一个形象类型,它蕴含某些字段,而对象类型必须蕴含这些字段,能力算实现了这个接口
- 联结类型(Union Types)
export type GraphQLType =
| GraphQLScalarType
| GraphQLObjectType
| GraphQLInterfaceType
| GraphQLUnionType
| GraphQLEnumType
| GraphQLInputObjectType
| GraphQLList<any>
| GraphQLNonNull<any>;
- 输出类型(Input Types)
export default new GraphQLInputObjectType({
name: "BlogPostInput",
fields: {_id: { type: GraphQLID},
title: {type: GraphQLString},
description: {type: GraphQLString},
},
});
查问和变更 (Queries and Mutations)
- 字段(Fields)
简略而言,GraphQL 是对于申请对象上的特定字段
query {
blogPosts {title}
}
{
"data": {
"blogPosts": ["title": "R2-D2"]
}
}
- 参数(Arguments)
query {blogPosts(id: "xxx") {
_id
title
}
}
{
"data": {
"blogPosts": [
"_id": "xxx"
"title": "R2-D2"
]
}
}
- 别名(Aliases)
query {blogs: blogPosts(id: "xxx") {title}
}
{
"data": {
"blogs": [
"_id": "xxx"
"title": "R2-D2"
]
}
}
- 片段(Fragments)
GraphQL 可复用单元,能够防止反复代码
query {one: blogPost(id: "59507b70729885c9097720fc") {...commonFields}
two: blogPost(id: "59507b8b729885c9097720fe") {
...commonFields
_id
description
}
}
fragment commonFields on BlogPost {title}
- 操作名称(Operation name)
query BlogPostOperationName {
blogPosts {
title
description
}
}
- 变量(Variables)
query BlogPostOperationName($id: ID = "59507b70729885c9097720fc") {blogPost(id: $id) {title}
}
- 指令(Directives)
query BlogPostOperationName($id: ID!, $withDescription: Boolean!) {blogPost(id: $id) {
title
description @include(if: $withDescription)
}
}
variables {
"id": "59507b70729885c9097720fc",
"withDescription": false
}
- 变更(Mutations)
mutation {addBlogPost (data: {title: "abcdefg", description: "abcdefg"}) {
title
description
}
}
- 内联片段(Inline Fragments)
query BlogPostWithComment($id: ID!) {blogPost(id: $id) {
title
... on BlogPost {description}
}
}
验证 (Validation)
通过应用类型零碎,你能够预判一个查问是否无效。这让服务器和客户端能够在有效查问创立时就无效地告诉开发者,而不必依赖运行时查看。
执行 (Execution)
一个 GraphQL 查问在被验证后,GraphQL 服务器会将之执行,并返回与申请的构造绝对应的后果,该后果通常会是 JSON 的格局
GraphQL 不能脱离类型零碎解决查问
内省 (Introspection)
咱们有时候会须要去问 GraphQL Schema 它反对哪些查问。GraphQL 通过内省零碎让咱们能够做到这点
{
__schema {
types {name}
}
}
{
__schema {
queryType {name}
}
}
GraphQL 最佳实际
GraphQL 标准特意疏忽了一些面向 API 的重要问题,例如解决网络、受权和分页。这并不意味着在应用 GraphQL 时没有针对这些问题的解决方案,只是因为它们并非 GraphQL 定义中的一部分,可代以工程上通行的做法来实现。
- HTTP
https://graphql.bootcss.com/l…
- JSON(应用 GZIP 压缩)
GraphQL 服务通常返回 JSON 格局的数据,但 GraphQL 标准 并未要求这一点。对于冀望更好的网络性能的 API 层来说,应用 JSON 仿佛是一个奇怪的抉择,但因为它次要是文本,因此在 GZIP 压缩后体现十分好
- 版本控制
尽管没有什么能够阻止 GraphQL 服务像任何其余 REST API 一样进行版本控制,但 GraphQL 强烈认为能够通过 GraphQL schema 的继续演进来防止版本控制
- 分页
https://graphql.bootcss.com/l…
- 服务器端的批处理与缓存
https://graphql.bootcss.com/l…
两种数据申请形式
- Queries
- Mutations
示例代码地址
graphql-koa-demo
材料
GraphQL 标准 https://spec.graphql.cn/
GraphQL 中文文档 https://graphql.cn/
对于前端不同框架也都有对于 Graphql 相干的库
- angular
官网:https://www.apollographql.com/
库:https://github.com/kamilkisie…
- vue
网站文档:https://vue-apollo.netlify.app/
库:https://github.com/Akryum/vue…
- react
库:https://github.com/apollograp…