GraphQL

前幾天在 Vapor 的 slack 上看到這則訊息:

於是乎,便點了進去看看什麼是 GraphQL

GraphQL v.s REST

首先,看到這個標題,要先了解一下什麼是「REST」;

我們在先前的文章中有提到關於 Firebase Database REST API 的內容,

但並沒有在文章內解釋其含義是什麼。

REST

REST(Representational State Transfer),是一種架構,而非協定或是標準;

透過 HTTP 協議所提供的動作(POSTGETPUTDELETE)來對資源進行 CRUD(Create、Read、Update、Delete),

並以 URI 的方式來指定資源:

  • POST /games:建立遊戲
  • GET /games:取得遊戲清單
  • PUT /games/123:修改 id = 123 的遊戲內容
  • DELETE /games/123:刪除 id = 123 的遊戲

在 iOS 開發的串接 RESTful API 的經驗中,不論是取得的資料,或是回傳回 server 的資料,

大多是以 JSON 的格式在做溝通。

前後端之間可以透過 RESTful 的方式進行明確的溝通,進而開發出相對應的功能。

 

REST 的缺點

但有時候還是會遇到一些問題

  • 會拿到多餘的欄位
  • 巢狀資源的處理
  • 越來越多支 API

會拿到多餘的欄位

有時候我們為了顯示一個商品,在畫面上需要呈現

  • 商品名稱
  • 價錢
  • 照片 URL

但可能在 GET /products/1 的時候,會拿到整個商品的資料回來:

  • 商品 ID
  • 名稱
  • 價錢
  • 剩餘數量
  • 照片 URL
  • 建立時間
  • 最後更新時間

不過在顯示端僅需要呈現三個項目,那麼其他回傳的資料就浪費了彼此之間的網路傳輸。

巢狀資源的處理

像是在一個畫面中,需要顯示「我的最愛」;

在 REST 的架構下,我們會設計出兩支 API:

  • GET /users/1/favorites:取得 id = 1 的會員的最愛清單
  • GET /books/123:取得 id = 123 的書本資料

我們會在第一支 API 中取得一個書本 ID 列表,再來呼叫第二支 API 來取得書本資訊;

如果將書本的資訊直接併入最愛之中,雖然可以減少查詢的次數,但又會在某些不需要關聯的時候,

而讓書本成為多餘的欄位。

於是乎就會越來越多支 API

上述幾種狀況,可能就會開始出現:

  • GET /products-with-photo
  • GET /products-with-price
  • GET /products-with-users

之類的,為了配合某些前端的顯示需求而特化的 API,為了一次取得多個物件回傳,

但這也破壞了 REST 原先的架構設計風格。

所以,Facebook 便在 2012 年開始在公司內部使用另一種架設風格來解決這些問題:

GraphQL

GraphQL 是由 Facebook 所提出的一種 query language,從 2012 年內部開始使用,到 2015 年 7 月開源

其精神便是將所有的 API 都統整成一支 GraphQL 的 API:

  • GET /graphql?query={ user(id: “1″) { name, address { zipCode } } }

回傳的資料由呼叫 API 的人決定,有點像是讓呼叫人的負責下 query 的條件。

讓前後端共同使用一份 schema 來定義出個物件的 type 和定義好 Query 這個物件的內容,

再來就由呼叫方來自由發揮需要取得哪些資訊自訂組裝。

比較強烈的比較在於:

  • 只有一支 API(也就是只有一個 endpoint)
  • 可以自行處理巢狀資料
  • 可以自行決定拿到哪些欄位

進而改善上面所提到的問題。

 

結論

對於 iOS 的開發人員而言,是一種蠻新潮且有趣的串接方式,

但在後端就不知道是一個怎樣的複雜程度了⋯⋯畢竟我比較著重在 iOS 的應用方面,

有興趣的人可以看看我所一開始看的這篇文章