前端應該知道的GraphQL

simbawu發表於2018-04-28

本文主要結合GitHub GraphQL API,從前端使用者的角度來談GraphQL,沒有GraphQL專案的同學可以拿GitHub GraphQL API練手,具體程式碼可參見我的GitHub Blog,歡迎star、fork。

為什麼需要GraphQL?

以我的部落格為例,目前列表頁,每篇文章需要的資料結構如下:

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

而文章詳情頁的資料結構為:

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

又想記錄下文章的瀏覽量,日後成為大V,再展示出來 hhh~

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

那麼問題來了:兩個頁面的資料結構title和updateAt的資料是重複的,而body是不同的,並且還有一個希望現在就設計好以後需要的時候再用到的view欄位。如果為了方便,只寫一個介面,同時返回bodyText和bodyHTML,那總有資料是多餘的,這樣也不合理。但如果分兩個介面,又顯的有點麻煩和浪費。

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

如果能從源頭出發,介面返回的資料不是由生產方(後端),而是由使用方(前端)來決定,就可以達到所見即所得的效果,這時候GraphQL也就應運而生了。

什麼是GraphQL?

先貼官網:英文 | 中文

GraphQL 既是一種用於 API 的查詢語言,也是一個滿足你資料查詢的執行時。 GraphQL 對你的 API 中的資料提供了一套易於理解的完整描述,使得客戶端能夠準確地獲得它需要的資料,而且沒有任何冗餘,也讓 API 更容易地隨著時間推移而演進,還能用於構建強大的開發者工具。

也就是說,GraphQL能夠在你呼叫api的時候來決定api返回的資料結構,以此達到精準、沒有冗餘的拿到所需要的資料。GraphQL這麼厲害,是如何做到的呢?我們先從我的部落格文章詳情頁介面入手來揭示GraphQL的廬山真面目:

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 | 知乎 | 簡書 | 掘金

相關文章