Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
# Overview
- GraphQL
- 是 query language
- 也是一份規格
- GraphQL engine
- spec 的實作
- 已有多種語言版本的實作(FB 官方提供 js 實作)
- Relay
- 一個 data fetching framework
- 專用於 GraphQL 的 react client,用來連接 GraphQL server
- 目前僅知有 js 實作
# GraphQL
# 定位
- micro services 的 API gateway
- 可視為 facade pattern 的一種
[圖](API-gateway-1.png)
[圖](API-gateway-2-micro-service.png)
# 優點
- 提供明確資料接口、型態
- 提供 cache 機制
- 提供 paging 能力
- 目前已知實作
- https://github.com/cryptix/go-graphql
- https://github.com/rmosolgo/graphql-ruby
- https://github.com/dittos/graphql-py
- https://github.com/andimarek/graphql-java
- https://github.com/webonyx/graphql-php
- https://github.com/sangria-graphql/sangria
- https://github.com/joemcbride/graphql-dotnet
# 缺點
- 資料存取邏輯仍需人工撰寫
- 已有自動化方案
- https://github.com/RisingStack/graffiti (ORM)
- convert your existing models into a GraphQL schema and exposes it over HTTP
- 目前還不支援 mutation
- https://github.com/solidsnack/GraphpostgresQL
- https://github.com/RisingStack/graffiti-mongoose
- https://github.com/mickhansen/graphql-sequelize
- https://github.com/brysgo/graphql-bookshelf
- server 上組合多方資料源花的時間成本可能更高
- 除非原本就用 Graph DB,例如 Neo4j
[圖](API-gateway-1.png)
- 使用 connection, edges 等怪異名詞
# 技術細節
- schema.js 是重點
- 宣告資料的 Type 與 relationship
- 例如一個 User 有許多 todos,此關聯該如何定義?
- database.js
- 串接資料源,例如 REST API 或各種 db
# Relay
# 定位
- 介於 client 與 server 間的 connector
# 優點
- query 與 mutation 都用相同語言(GraphQL)
- 每個元件外包一個 relay container 省去層層傳遞
- data 不用透過 context 或 props 層層傳遞
- app 結構變的扁平化,幾乎只有一階
- 資料與元件緊密相依
- 易於管理
- 不會 over/under fetching
- 程式易讀、易開發、不易犯錯
- 只要看 view component 內容,就知道它會用到哪些資料
- 元件從此真正完全封裝,也可隨意移到任何層級內,不用擔心資料接口會丟失(因為以往是由上到下逐層傳遞)
- 集中式 store 代為處理資料正規化、cache、存取操作
- made efficient through caching, batching, re-use, and other means to reduce the size of queries
- 這些事原本都要工人智慧來做,現在它自動做好了
- 將來會支援 server 之外的資料源,例如 in-memory, file system, device APIs,也能 offline 操作
- 便於分工,一個人負責寫 schema 與所有 muation
- 這個人可能就是原本的後端工程師,因為 REST API 也是他寫的
- 其它 component developer 只要會用 graphql 語法就好
# 缺點
- 目前 client 端只有 react 實作
- ios/android 無法使用,只能繼續透過 REST API 操作
- 所有 CUD 都要寫一支 mutation js,內含六大步驟
# 技術細節
- 功能
- 提供統一的 store
- 與 GraphQL server 溝通(透過標準 GET/POST 操作)
- 負責所有 model 的 normalization, cache, update...
[圖](relay-structure.png)
- 提供封裝的 container
- 它就是 container component
- 大量應用 Higher Order Component 技巧
- 負責 data fetching, binding, redrawing
[圖](Containers-HOC-Relay.png)
- query 的範例
// todo.js
fragments: {
todo: () => Relay.QL`
fragment on Todo {
complete,
id,
text,
}
`,
viewer: () => Relay.QL`
fragment on User {
${ChangeTodoStatusMutation.getFragment('viewer')},
${RemoveTodoMutation.getFragment('viewer')},
}
`,
},
- mutation 的範例
- 新增一筆 todo
_handleTextInputSave = (text) => {
Relay.Store.update(
new AddTodoMutation({text, viewer: this.props.viewer})
);
}
- mutation 的六個關鍵步驟
fragments: 宣告 mutation 操作過程中一定要取得的欄位
getOptimisticResponse: 為了實現 optimistic update 而提供的假資料
getFatQuery: mutation 後要從 server 取回的新資料
getMutation: 指定要操作的 mutation 名稱(要事先定義在 schema.js 內)
getConfigs: mutation 後從 server 取回新資料該如何更新本地端舊資料,注意這裏有四種 type:
FIELDS_CHANGE, NODE_DELETE, RANGE_ADD, RANGE_DELETE
getVariables: 取得 mutation 要用的變數,例如新輸入的 text 內容
- routing
- 目前看來將與 react-router 配合
# 結論
- 採用 GraphQL/Relay 的考量
→ 省掉的部份
- 原本 client 要手工維護的各種 CRUD 與 optimistic update code 皆可省略
→ 不能省的部份
- client 還是要寫 RemoveTodoMutation.js 來定義更新 logic
- getFatQuery(), getConfigs(), getOptimisticResonpose()等
← 雖然最後一定是 copy/paste 直接用
← 並且將來可省掉這步
- server 上要多一份 schema.js ,頗長
- 而且 CRUD 操作要用它定義的 graph connection 語法,要重學
- 目前 GraphQL/Relay 的規格與範例都還在快速演化中,至少等兩個月再進場不遲
- 現階段摸熟 redux 與週邊配套方案效益最高
- 參考
- Falcor
- netflix.github.io/falcor/starter/what-is-falcor.html
- Netflix 推出,以 JSON graph 為主的解決方案
- Relay 二三事 (David Chang)
- https://goo.gl/jzOKfV
- Relay-Chat example (Edward Chen)
- https://github.com/transedward/relay-chat
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment