GraphQL v.s REST
首先,看到這個標題,要先了解一下什麼是「REST」; 我們在先前的文章中有提到關於 Firebase Database REST API 的內容, 但並沒有在文章內解釋其含義是什麼。
REST
REST(Representational State Transfer),是一種架構,而非協定或是標準; 透過 HTTP 協議所提供的動作(POST、GET、PUT、DELETE)來對資源進行 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 } } }
{
"name": "Archie",
"address": {
"zipCode": "12345"
}
}
回傳的資料由呼叫 API 的人決定,有點像是讓呼叫人的負責下 query 的條件。 讓前後端共同使用一份 schema 來定義出個物件的 type 和定義好 Query 這個物件的內容, 再來就由呼叫方來自由發揮需要取得哪些資訊自訂組裝。 比較強烈的比較在於:
- 只有一支 API(也就是只有一個 endpoint)
- 可以自行處理巢狀資料
- 可以自行決定拿到哪些欄位 進而改善上面所提到的問題。
結論
對於 iOS 的開發人員而言,是一種蠻新潮且有趣的串接方式, 但在後端就不知道是一個怎樣的複雜程度了⋯⋯畢竟我比較著重在 iOS 的應用方面, 有興趣的人可以看看我所一開始看的這篇文章。