Meta 當初還是 Facebook時候 發現一個瓶頸是常常會over fetching or under fetching
很多頁面或component需要的資料很像但因為那個API就是給這麼多東西而我只需要一點點
很多資源就被浪費掉了 比如網路頻寬畢竟當時的data還沒有現在這麼快
或是有些component需要很多API來湊齊需要的資料就會等很久
當然也可以一個API叫這些 這完全是OK的
不過就是不太flexible
long story short 最後開發了GraphQL
GraphQL其實是個query language
如果你只有GraphQL的話它本身其實沒辦法給你什麼
GraphQL後面需要接東西
它強大的地方是面對前端只有一個API gateway
我要什麼query都是和一個簡單來說server溝通
但GraphQL可以根據這個query 看你怎麼接 和其他Rest API拿或是和資料庫拿甚至只是一個JSON檔案
GraphQL有很多公司有做比如Prisma和Apollo
我現在和前公司都是用Apollo所以講的東西有可能是Apollo才有但大致上那個idea應該是差不多的
GraphQL有三個components
schema, resolver, data source
schema: query, mutation
在RESTful世界中有GET POST這類的method
在GraphQL裡面任何取資料的method都是query
而需要增加或是修改資料的都是mutation
定義完這些後你需要定義這些query mutation拿的input和return的data structure長什麼樣子
類似REST裡面的parameter和response
這些都寫在一個graphql檔案裡面
下一步是
resolver: schema進來 query進來 GraphQL應該要把這個query match到哪一個data source
data source: 資料來源從哪裡來 比如另一個Rest API, database, or 另一個GraphQL server
基本上我們就是傳一個fetch 或是 gRPC request把data傳回resolver把這些資料和schema接起來
GraphQL的特點是我的query想要返回多少data比如我user只要id和email
我拿到的就是只有id和email而不會連帶其他東西都來
浪費頻寬也浪費memory
今天我若需要發三個不同的query
我可以在前端把三個query寫在同一個request上面
我們就只要傳一個request就好而不是做三個個別的request
把和server交流的時間省了下來
另一個特點是discoverability, 每個GraphQL產品應該都有帶Introspection
會告訴你說有什麼query可以用 input是什麼然後schema是什麼
這本身就是一個API document
想要什麼query就先找看看有沒有類似的
沒有我們再來加
這邊就得特別提一下Apollo有個產品or功能就是Federation
可以有很多個subgraph但對外面來說都是一個graph
這和micro services特色蠻像的 也可以單獨的做deployment和publish
不管graph有多少個或是schema有多大 前端只要面對一個api server就好了
我今天找到的query可能不是我們組寫的而是別的組寫的
如果這資料結構是你要的你就可以直接用了而不用請後端寫一個給你
這就是我所謂的被發現的能力
我自己是不希望在每個endpoint的Swagger上面ctrl F找我要的API
在schema裡面除了每個data都定義一個type比如integer, string這樣
我們也會自定義自己的type
而且這些type是可以被share的不管是自己組的或是別人的graph
我如果今天有個User type
我可能有個query是單純return使用者資料
另一個是回傳購買紀錄但裡面也有個user資料
雖然兩個不同的team但我們可以共用這個type
這對溝通來說幫助很大而且我們前端也能很快地掌握這到底確切有什麼資料
每個技術都有它的缺點所以GraphQL也不例外
對一個小專案來說GraphQL其實有點複雜
和REST api相比之下你得做很多準備才能吧GraphQL弄好而這只是後端這邊的
前端也得把Apollo Client弄好而且如果還有用TypeScript你可能也會希望把type弄好
什麼都還沒開始弄就已經滿頭大汗準備下班了
然後等新人來再教他們這些東西
那個learning curve應該稍微抖一點
GraphQL standard都是用POST來傳這些request的而且99%的status code都是200
意味著caching可能是個問題 大部分的infra都不會cache POST
Apollo有方法把request轉成GET所以還算是個解決方案
但status code都是200可能會造成一些小困擾
雖然Apollo Client是回傳error object因為GraphQL把error放在repsonse裡面
但有些error reporting會去看這個status code 代表你前端想debug去看reporting時候可能不會看到說哪個query其實報錯了
得多做一步去後端看一下
雖然不是特別大的問題 就有些人可能會覺得怪怪的
要不要採用GraphQL我覺得這不算是一個單純的技術問題而是管理上的問題
公司裡面組之間有沒有明確的責任和domain規範
GraphQL能不能幫你們做到更好的組織和管理
上述說的東西其實REST都可以做到
只是今天就是回歸到那個問題我們要解決什麼痛點
有個Pattern叫backend for frontend
GraphQL是個非常貼切的例子
GraphQL schema比較是為了前端設計的而不是資料庫的table設計的
它就是一個類似data transformation layer
要在前端做這些也可以
把多個rest api response在前端整理一下再顯示
但若有很多個app這麼做就挺浪費時間
而且這種事情在server上做比較簡單也快