前端應該知道的GraphQL

本文主要結合GitHub GraphQL API,從前端使用者的角度來談GraphQL,沒有GraphQL項目的同窗能夠拿GitHub GraphQL API練手,具體代碼可參見個人GitHub Blog,歡迎star、fork。javascript

爲何須要GraphQL?

以個人博客爲例,目前列表頁,每篇文章須要的數據結構以下:前端

{
    "title": "前端應該知道的GraphQL",
    "updatedAt": "2018-04-22T03:46:34Z",
    "bodyText": "本文主要結合...",
}
複製代碼

而文章詳情頁的數據結構爲:java

{
    "title": "前端應該知道的GraphQL",
    "updatedAt": "2018-04-22T03:46:34Z",
    "bodyHTML": "<p>本文主要結合...",
}
複製代碼

又想記錄下文章的瀏覽量,往後成爲大V,再展現出來 hhh~node

{
    "title": "前端應該知道的GraphQL",
    "updatedAt": "2018-04-22T03:46:34Z",
    "bodyHTML": "<p>本文主要結合...",
    "view": "29898",
}
複製代碼

那麼問題來了:兩個頁面的數據結構title和updateAt的數據是重複的,而body是不一樣的,而且還有一個但願如今就設計好之後須要的時候再用到的view字段。若是爲了方便,只寫一個接口,同時返回bodyText和bodyHTML,那總有數據是多餘的,這樣也不合理。但若是分兩個接口,又顯的有點麻煩和浪費。git

這還只是一個簡單的例子,平時開發過程當中,需求變化特別頻繁,遇到的問題也會更復雜,目前主流的RESTful API所暴露出來的問題也愈來愈明顯。github

若是能從源頭出發,接口返回的數據不是由生產方(後端),而是由使用方(前端)來決定,就能夠達到所見即所得的效果,這時候GraphQL也就應運而生了。json

什麼是GraphQL?

先貼官網:英文 | 中文segmentfault

GraphQL 既是一種用於 API 的查詢語言,也是一個知足你數據查詢的運行時。 GraphQL 對你的 API 中的數據提供了一套易於理解的完整描述,使得客戶端可以準確地得到它須要的數據,並且沒有任何冗餘,也讓 API 更容易地隨着時間推移而演進,還能用於構建強大的開發者工具。後端

也就是說,GraphQL可以在你調用api的時候來決定api返回的數據結構,以此達到精準、沒有冗餘的拿到所須要的數據。GraphQL這麼厲害,是如何作到的呢?咱們先從個人博客文章詳情頁接口入手來揭示GraphQL的廬山真面目:api

let data = {
  query: `query { repository(owner:"simbawus", name: "blog") { issue(number: ${articleId}) { title updatedAt bodyHTML } } }`
};

Actions.getIssues(data).then((res) => {
  let issue = res.data.data.repository.issue;

  this.setState({
      title: issue.title,
      updatedAt: new Date(issue.updatedAt).format('yyyy-MM-dd'),
      bodyHTML: issue.bodyHTML
  })
})
複製代碼

這就是一個基於GitHub GraphQL API的請求,跟普通請求惟一的區別就在請求參數data,並非 JSON 對象,而是一個字符串,這個字符串描述了客戶端但願服務端返回數據的具體結構,以下JSON:

{
    "data": {
        "repository": {
            "issue": {
                "bodyHTML": "<p>本文主要結合...",
                "title": "前端應該知道的GraphQL",
                "updatedAt": "2018-04-22T03:46:34Z",
            }
        }
    }
}
複製代碼

結合這個例子,我來介紹GraphQL的幾個核心概念:

query & mutation

query的中文意思是查詢,也就對應RESTful標準中的get,而mutation的意思是變動,對應post、delete、patch和put。

connection

connection讓你能在同一個請求中查詢關聯的對象。經過connection,你只須要一個GraphQL請求就能夠完成RESTful API中多個請求才能作的事。

好比,GitHub GraphQL API文檔中,咱們在查詢issue對象的同時,還能夠查labels對象。

let data = {
  query: `query { repository(owner:"simbawus", name: "blog") { issue(number: ${articleId}) { title updatedAt bodyHTML } labels(first: 100){ nodes{ name } } } }`
};
複製代碼

field

field是你能夠從對象中獲取的數據單元。正如GraphQL官方文檔所說:「GraphQL查詢語言本質上就是從對象中選擇field」。全部的GraphQL操做必須指明到最底層的field,而且返回值爲標量,以確保響應結果的結構明白無誤。

argument

argument跟RESTful API標準中一致,表示咱們在請求該接口是傳的參數,好比上面issue的number 參數,表示請求的第${articleId}個issue。

對於前端來講,在查詢GraphQL API的時候基本都要了解上面說的這幾個概念,具體應用可參見個人這篇文章如何利用GitHub GraphQL API開發我的博客?。詳情代碼可查看個人github:simbawus/blog,歡迎star、fork。

GraphQL的將來

GraphQL的優點想必你們都瞭解了,但爲什麼這麼好的技術並無獲得普遍的應用和推廣呢?

  1. 要在前端爽爽地使用 GraphQL,必須得在服務端搭建符合 GraphQL spec 的接口,基本上是整個改寫服務端暴露數據的方式。痛點是前端的,卻要後端來改造,誰會去作?
  2. 改爲GraphQL對用戶體驗來講並無什麼提高,並且對後端水平要求也高,改起來不簡單,須要花費大量的時間,老闆不用付你工資的嗎?
  3. GraphQL意味着一箇中心化的API網關,中心化流量要求巨大的中心化集羣,技術上運維上又是一個難題。

基於以上,GraphQL目前基本也就一些比較有技術追求和實力的創業公司和一線大廠在使用,但願Facebook能更進一步,給出一個基於雲端的解決方案,解放前端。

歡迎討論,點個贊再走吧~

文章同步於如下社區,能夠選一個關注我噢 。◕‿◕。

simbawu | github | segmentfault | 知乎 | 簡書 | 掘金

相關文章
相關標籤/搜索