昨天討論完 RESTful API,今天來看看截然不同的 GraphQL!
GraphQL 到 2015 年才對外發布,但在這之前,REST 的概念從 2000 年就已經提出,大家也用了十多年了,幾個顯著的問題,昨天也討論過了。
如果一個頁面要呈現多種 schema 的資料,比如一個 blog 系統,我手上有 user 的 id,需要呈現這樣的畫面:
如果是用 RESTful API,可能會需要打三次 API:
/user/<id>
/user/<id>/posts
/user/<id>/followers
而且以第一支 API user 來說,即便我只需要 user 的名字拿來顯示,後端仍有可能幫我將生日、星座、血型、祖宗十八代(?)都撈出來,但至少我在這個頁面是不需要多餘的資訊的,除了浪費頻寬,資料多傳就增加了 bug 出現的機率。
GraphQL 是一個針對 API 的查詢語言
A query language for your API
最大的賣點在於,GraphQL 採用 declarative data fetching:
fetch
)這部分是參考 How To GraphQL,其實也沒有什麼神奇的魔法,步驟之所以會變得簡單,單純就是因為 GraphQL 將其他雜事處理掉了。
回到上面 user blog 的問題,如果是使用 GraphQL 來處理,可能會描述這樣子的資料結構:
query {
User(id: "er3tg439frjw") {
name
posts {
title
}
followers(last: 3) {
name
}
}
}
由於是前端自行宣告,需要取得哪些資料,所以後端回傳的資料是「精準」的,不多也不少,避免了這兩種狀況:
如果觀察過 GraphQL 前端發送出去的 request,會在 payload 發現,雖然是送出長得很像 JSON 的結構,但實際上它是個 string
GraphQL 會將查詢的語法透過解析器轉換成語法樹,再遞迴呼叫每個欄位對應的 resolver,透過它去處理每個欄位該產生什麼值,最後匯集起來一次回傳。
簡單區分了三種類型,且大多時候只會用到 query 與 mutation,相對來說好懂很多:
針對現在前端裝置愈來愈多元,最基本就會有 web 與 app 端,在後端同一個情況下,不同平台所需的資料數量、格式都不同,能負擔的資料傳遞速度也不同(app 顯然不能傳太大量的資料)。
因此在這種情況下,GraphQL 做為一個 API 的查詢語言是非常方便的,因為不管你的 client 用什麼寫,反正只要傳送的 request 符合 GraphQL 的格式,就都通用!而且還可以只選擇自己真正需要的資料。
同時,如果系統的 schema 設計很複雜,比如像是 Facebook,同一個頁面同時要呈現發文者、文章、like、留言、留言的 like 等,這樣的資料型態也很適合 GraphQL,可以一次 request 就取得不同種類的資料。
GraphQL 也是我今年才開始使用的工具,其實剛開始用起來很卡,因為腦中已經是根深蒂固的 RESTful API 觀念,一次一個 API 一個資源,要轉移到 GraphQL 這種「圖像連結」的思維,反而費了我不少功夫。
的確工具是看狀況用的,即便 GraphQL 是比較新的產物,但也不是說任何環境都無腦使用就是最佳解,有時候還需要考量「適性」的問題,找到適合這個時間點的工具,才是重要的!