GitHub chose GraphQL for our API v4 because it offers significantly more flexibility for our integrators. The ability to define precisely the data you want—and only the data you want—is a powerful advantage over the REST API v3 endpoints. GraphQL lets you replace multiple REST requests with a single call to fetch the data you specify.
For more details about why GitHub has moved to GraphQL, see the original announcement blog post.
背景
GraphQL 的核心是一套數(shù)據(jù)查詢語言的規(guī)范曼尊,是 Facebook 在2012年開發(fā)的酬诀,2015年開源,F(xiàn)acebook 內(nèi)部已經(jīng)廣泛應(yīng)用骆撇,用于替代 REST料滥。
GitHub 為什么選擇 GraphQL?這是很多用戶關(guān)心的問題艾船,Github 對此做了解釋葵腹。
REST 問題所在
首要問題就是擴(kuò)展性方面,隨著 API 的不斷發(fā)展屿岂,會(huì)變得越來越臃腫践宴。
REST API 的方式:服務(wù)端定義一系列的接口,客戶端調(diào)用自己需要的接口爷怀,獲取目標(biāo)數(shù)據(jù)進(jìn)行整合阻肩。
例如用戶接口,剛開始時(shí)运授,返回的信息會(huì)比較少烤惊,例如只有: id,name
。
后來用戶的信息增加了吁朦,就在用戶接口中返回更多的信息柒室,例如:id,name,age,city,addr,email,headimage,nick
。
但可能很多客戶端只是想獲取其中少部分信息逗宜,如: name,headimage
雄右,卻必須得到所有的用戶信息空骚,然后從中提取自己想要的。這個(gè)情況會(huì)增加網(wǎng)絡(luò)傳輸量擂仍,并且不便于客戶端處理數(shù)據(jù)囤屹。
還有一個(gè)不方便的地方,就是客戶端在某個(gè)需求中逢渔,可能需要調(diào)用多個(gè)獨(dú)立的 API 才能獲取到足夠的數(shù)據(jù)肋坚。例如:客戶端要顯示一篇文章的內(nèi)容,同時(shí)要顯示評論肃廓、作者信息智厌,那么就可能需要調(diào)用文章接口、評論接口亿昏、用戶接口,這種方式非常不靈活档礁。
GitHub 還遇到其他一些 REST API 不好處理的問題角钩,例如:想要確保客戶端提供的參數(shù)的類型安全呻澜;想要從代碼生成文檔递礼;想要識(shí)別每個(gè)端點(diǎn)的 OAuth 請求范圍 ……
GraphQL 的優(yōu)勢
GraphQL 簡單來說就是:取哪些數(shù)據(jù)是由客戶端來決定。
在 REST 中羹幸,給哪些數(shù)據(jù)是服務(wù)端決定的脊髓,客戶端只能從中挑選,如果 A 接口中的數(shù)據(jù)不夠栅受,那就再請求 B 接口将硝,然后從他們返回的數(shù)據(jù)中挑出自己需要的。
在 GraphQL 中屏镊,客戶端直接對服務(wù)端說想要什么數(shù)據(jù)依疼,服務(wù)端負(fù)責(zé)精確的返回目標(biāo)數(shù)據(jù)。
例如而芥,你想要獲取用戶的幾個(gè)屬性信息律罢,你的 GraphQL 請求就是這樣的:
{
viewer {
login
bio
location
isBountyHunter
}
}
相應(yīng)的返回信息是這樣的:
{
"data": {
"viewer": {
"login": "octocat",
"bio": "I've been around the world, from London to the Bay.",
"location": "San Francisco, CA",
"isBountyHunter": true
}
}
}
你可以看到 JSON 響應(yīng)中的鍵和值與查詢字符串中的術(shù)語一致。
再看一個(gè)復(fù)雜的例子棍丐,例如你想知道你給多少個(gè)項(xiàng)目點(diǎn)亮過星星误辑、最初3個(gè)項(xiàng)目的名字、及他們stars歌逢、forks巾钉、watchers 、open issues 的總數(shù)秘案。
GraphQL 請求:
{
viewer {
login
starredRepositories {
totalCount
}
repositories(first: 3) {
edges {
node {
name
stargazers {
totalCount
}
forks {
totalCount
}
watchers {
totalCount
}
issues(states:[OPEN]) {
totalCount
}
}
}
}
}
}
響應(yīng):
{
"data":{
"viewer":{
"login": "octocat",
"starredRepositories": {
"totalCount": 131
},
"repositories":{
"edges":[
{
"node":{
"name":"octokit.rb",
"stargazers":{
"totalCount": 17
},
"forks":{
"totalCount": 3
},
"watchers":{
"totalCount": 3
},
"issues": {
"totalCount": 1
}
}
},
{
"node":{
"name":"octokit.objc",
"stargazers":{
"totalCount": 2
},
"forks":{
"totalCount": 0
},
"watchers":{
"totalCount": 1
},
"issues": {
"totalCount": 10
}
}
},
{
"node":{
"name":"octokit.net",
"stargazers":{
"totalCount": 19
},
"forks":{
"totalCount": 7
},
"watchers":{
"totalCount": 3
},
"issues": {
"totalCount": 4
}
}
}
]
}
}
}
}
你只發(fā)出了一個(gè)請求來獲取所需的所有數(shù)據(jù)睛琳。
GitHub GraphQL API 體驗(yàn)
網(wǎng)址:GitHub GraphQL API