現在市面上有不少GraphQL(下面簡稱gql)的資料了,GraphQL這個規範或者說思想出來也有三年多了,不少公司有了實踐,有成功的,也有留下一堆坑填不了跑路的?。大掘金上有篇譯文叫《 REST API 已死,GraphQL 長存 》,長時間過去了,用的人也不多?,所以分享一下基礎知識,互相學習。最後,我覺得在偏傳統的2B SaaS類領域,gql的潛力還沒有被完全釋放。
它是什麼?從哪裡來?要幹什麼?
簡單地講,對於前端,它就是讓你舒舒服服發請求的
嚴格的說,它是一種api設計思想,用來取代restful api的一種前端處於主導地位的api規範。它把前端所需要的api用類似圖資料結構(graph)的方式展現出來,讓前端很方便的獲取所需要的資料。
起源,restful api的問題
如果採用restful api的話,後端要持續維護api doc,但是實際場景是這樣的:
1.來了新需求,後端先評估和開發,後端弄得差不多,前端才開始,然後中間後端一頓猛改
2.由於多種原因,後端經常自己偷偷改掉傳參或者返回值,完了介面報錯,測試姐姐把前端叫過去一頓批,前端一臉懵圈,仔細檢查,發現問題,找後端撕X,這樣一個迴圈非常影響開發效率。
gql出現
由於上面這一堆的問題,facebook公司2012年內部實踐了GraphQL,15年剛開源的時候引起了很多大公司和社群關注,落地了很多規範和框架。需要了解詳細歷史可以看看底下的youtube視訊。
這種叫GraphQL的東西幫助人們經過一系列定義和規範,可以傳送gql請求非常方便的拿到想要的資料,甚至還可以修改資料,而不用後臺的配合,而且一旦Schema確定(資料庫那邊定義好),前後端就可以快速並行開發,例如下圖獲得某個使用者的資訊,我想要這個使用者的什麼屬性就寫什麼,graphiQl工具可以進行完整的詳細的提示,請求主體簡單明瞭
query{
student{
id
name
age
}
course{
id
title
}
}
複製程式碼
gql理想使用場景
資料庫建好模型,前後端可以同步開始開發需求,前端只有少數需要依賴後端介面,前端開發過程中可以方便的拿到任何想要的資料,從而節省大量聯調介面的時間,迅速的完成一個專案。
實現原理
gql的實現挺複雜的,程式碼有點難懂,不過原理說起來比較簡單易懂?
var { graphql, buildSchema } = require('graphql');
// Construct a schema, using GraphQL schema language
var schema = buildSchema(`
type Query {
hello: String
}
`);
// The root provides a resolver function for each API endpoint
var root = {
hello: () => {
return 'Hello world!';
},
};
// Run the GraphQL query '{ hello }' and print out the response
graphql(schema, '{ hello }', root).then((response) => {
console.log(response);
});
複製程式碼
如上就是一個最簡單的node版的gql伺服器
gql把定義好的schema拿到,用root之類的resolve解析器去解析傳送來的'{ hello }'
請求,然後返回給相應的json值。上面程式碼列印出的response如下
{
data:
{
hello: 'Hello world!'
}
}
複製程式碼
當然,resolve逐層解析會有一些問題,如果resolve請求資料庫,就要用到DataLoader
DataLoader是gql伺服器效能的關鍵一環,也是gql社群的主要推動完善方向,就像react裡面的shouldComponentUpdate一樣制約著gql伺服器的效能。
DataLoader 能讓我們從資料庫讀取資料並讓資料能被 GraphQL 處理,我們使用 DataLoader,而不是直接通過 SQL 查詢從資料庫獲取資料,將 DataLoader 作為代理以減少我們實際需要傳送給資料庫的 SQL 查詢。 DataLoader 使用批處理和快取的組合來實現。如果同一個客戶端請求會造成多次請求資料庫,DataLoader 會整合這些問題並從資料庫批量拉取請求資料。DataLoader 會同時快取這些資料,當有後續請求需要同樣資源時可以直接從快取獲取到。
具體使用
通過服務端對請求的後設資料的type進行嚴格的定義,我們只要在客戶端傳送gql請求就能返回期望的相應型別的資料
下圖是請求格式,query【請求】,mutation【修改】和subscribe【訂閱】是三種api傳送方式,query用的多一些,mutation相對傳統的restful來說不夠可靠和安全,subscribe類似websocket
query
{
schema {
types {
id
name // 獲取根欄位名
fields {
id
name // 獲取欄位名
}
}
}
}
複製程式碼
正式環境下書寫的大概長下圖這樣,一些標量、片段之類的細節不多說了,看GraphQL中文官方網站說的很詳細了
輔助工具graphiql和playground
前端進行gql開發的神器,十分好用,帶智慧提示,這個schema裡面都有哪些type,每個型別都會返回什麼型別的值,數字還是字串,一目瞭然,比看api文件快得多
graphiql是網頁版,足夠好用
playground對graphiql更進一步,多實現了一些小功能,是electron構建的應用,類似RN裡面的react-devtools
封裝gql的客戶端&服務端框架
使用gql過程中可以自己基於業務進行二次封裝,也可以使用現成框架,用於更方便的發gql請求,並與react或者vue元件進行互動。社群框架太多了,就挑幾個說一下,具體可以看github上搜集的graphql資料 全
apollo-boost
包含下圖5個框架,與react-apollo一起搭配使用,是apollo社群推薦的前端使用方式,開發起來快,但是擴充修改不太方便,不適合自定義的公司專案
apollo-client
上圖5個框架中最核心的一個,將各類介面微服務和資料庫操作進行封裝,整合redux,更易使用,但是略顯臃腫,個人覺得,gql與資料庫直接通訊才是優勢,對接rest等有點繞遠路了。
relay
facebook官方前端快取框架,與apollo-client類似,star數比apollo-client要高2k,具體使用起來差不多
apollo-server
apollo-server是一個在nodejs上構建grqphql服務端的web中介軟體,支援express、koa等,瞭解不多,畢竟gql伺服器端支援很多後端語言,java等主流語言都可以封裝gql服務端
graphpack
號稱零配置gql伺服器,適合迅速學習搭建gql伺服器
原理:高度封裝了apollo-server,利用webpack和nodemon本地開啟一個gql伺服器
Gatsby
GatsbyJS這個框架國外挺火的,是一個優秀的靜態網站生成框架,優點是搭建起來,維護相當方便,甚至可以交給完全不懂程式設計的人。
特點是極其適合科學類介紹網站以及各種框架類文件(最適合建立markdown部落格),高度封裝了gql和markdown解析外掛。
和restful比較的優缺點
優點
- 優點就是後端可以少招幾個寫介面的?,可能會節約成本
- 前後端一起開發,節約工期
- 較少維護api文件,節省精力
說了這些,其實單對於前端來說,幫助不算特別大?
缺點和難推廣的地方
-
後端或者中間層把gql封裝相應業務對接資料庫是難點,需要高階人力
-
需要前端多少學一點類sql語句,不過大部分場景可以封裝好固定的sql語句
-
封裝gql不好會產生sql效能問題,三級巢狀聯查還有n+1的老問題又會冒出來,需要持續優化
-
前端排除bug需要一定的後端知識,前後端架構多少了解一些
總結
1.如果嘗試開發graphql專案,建議直接上apollo全家桶
2.隨著社群越來越成熟,前端入門門檻也在降低,graphql可以一試
3.當前技術來說,graphql只適合對接資料庫的查詢,其他開發成本還是過高
4.儘早上車,多學一門是一門,技多不壓身
篇幅所限,只是走馬觀花的介紹,每個小點展開都是一篇文章,就不多贅述了,如果大家想體驗一下gql,帶來的生產力提升絕對是物超所值的!大家有看不明白的地方或者作者說錯的地方,歡迎在評論區留言,我會著手修改?,另外,因為個人認知研究不斷深入和前端技術快速更迭,這篇文章也會持續的進行更新維護
蒐集的優秀資料
市面上一些優秀的資料,歡迎大家補充!