GraphQL 入門: 簡介
GraphQL 入門: Apollo Client - 簡介
GraphQL 入門: Apollo Client - 安裝和配置選項
GraphQL 入門: Apollo Client - 鏈接到數據
GraphQL 入門: Apollo Client - 網絡層
GraphQL 入門: Apollo Client - 開發調試工具
GraphQL 入門: Apollo Client - 持久化GraphQL查詢概要
GraphQL 入門: Apollo Client - 存儲API
GraphQL 入門: Apollo Client - 查詢(Batching)合併git
摘要: 本文采用 Elixir 語言開發的 Absinthe 做爲 GraphQL 的服務器端實現, 使用 Javascript 語言開發的 Apollo Client 做爲 GraphQL 的客戶端實現.github
持久化查詢, 是一種避免客戶端直接在查詢請求中包含查詢文檔的一種方式, 客戶端只須要傳遞給要執行查詢的ID, 服務器經過ID查詢到GraphQL文檔, 並在服務器端執行的過程. npm
優缺點:json
客戶端發送一個巨大的查詢過量消耗服務器的資源
segmentfault
客戶端能夠執行任意查詢,容易致使安全問題
安全
使用持久化查詢的目的:服務器
避免了客戶端發送GraphQL文檔, 減小網絡流量網絡
因爲GraphQL巨大的靈活性, 這也給安全帶來了挑戰, 這種機制實際上就是查詢白名單. 只有在白名單中的查詢纔是能被服務器執行的.ide
從直接發送查詢文檔轉換到持久化查詢的效果:函數
發送一個巨大的查詢再也不是一個問題
客戶端只能查詢服務器支持的限制性的GraphQL查詢(經過ID)
客戶端須要使用到 persistgraphql 工具來生成對應的查詢描述文檔. 用於完成查詢到ID的映射關係.
服務器端也須要作一樣的事情.
本節描述了服務器端和客戶端的具體實現.
服務器端採用Elixir語言做爲開發語言和運行環境
採用 Absinthe 包做爲 GraphQL 查詢的處理模塊
服務器端使用 Absinthe.Plug.DocumentProvider.Compiled
模塊讀取由 persistgraphql 工具生成的extracted_queries.json
文件來達到和客戶端一致.
服務器接收到客戶端發過來的查詢以下:
{ id: < 查詢 ID >, variables: < 變量JSON對象 >, }
經過查找ID, 把查詢轉換爲以下形式, 把ID替換爲查詢文本:
{ query: < GraphQL文檔 >, variables: < 變量JSON對象 > }
建立一個文檔Provider:
defmodule MyApp.ExtractedQueryProvider do use Absinthe.Plug.DocumentProvider.Compiled provide File.read!("/path/to/extracted_queries.json") |> Poison.decode! |> Map.new(fn {k, v} -> {v, k} end) # invert key/value end
添加該文檔 Provider 到 Absinthe.Plug
配置:
plug Absinthe.Plug, schema: MyApp.Schema, document_providers: [ Absinthe.Plug.DocumentProvider.Default, MyApp.ExtractedQueryProvider ]
當構建服務器端項目的時候, 讀取 extracted_queries.json
文件的內容, 解析, 並編譯爲Elixir模塊, 轉換爲中間表示, 並執行驗證. 這樣的持久化查詢請求就像經過ID請求一個普通的對象同樣.
注意:
詳細的服務器實現方法,請參考這個 Issue
另外Absinthe對持久化查詢的支持須要用到最新的代碼, 請使用absinthe_plug
的v1.3.0-alpha.0
及以上版本.
本節描述了持久化查詢的客戶端實現.
客戶端經過讀取 extracted_queries.json
文件, 把讀取到的文件內容轉換爲一個JSON對象, 客戶端向服務器發送請求以前, 先經過把整個GraphQL查詢做爲對象的字符串Key, 去找到對應的ID, 經過查找到的ID去執行GraphQL查詢.
這個GraphQL查詢文本
到查詢ID
映射的JSON對象格式以下:
{ < print(transform(GraphQL Document)) >: < ID >, }
Javascript 只容許字符串和數字做爲鍵, 所以咱們經過
graphql-js
模塊的
最終, 客戶端經過下面的僞代碼執行 GraphQL 查詢:
query(request: Request) { // 在 request.query 結構中查找對應的ID // 找到對應的ID // 經過GraphQL查詢變量把ID傳遞給服務器 // 返回一個Promise對象用於獲取服務器的返回結果 }
安裝 persistgraphql
命令行工具:
npm install --save persistgraphql # 或 yarn add persistgraphql # 全局安裝 yarn global add persistgraphql
persistgraphql
有兩個命令行參數, 分別表示輸入和輸出, 輸入能夠是當個文件或者目錄名稱, 路徑可使相對或絕對路徑, 安裝好後, 能夠執行:
persistgraphql queries.graphql
生成 extracted_queries.json
文件. 若是指定的輸入是一個目錄, 那麼 persistgraphql 會去查找該目錄下的所後綴爲 .graphql
的文件. 你能夠用GitHunt-React 這個項目來實際練習一下.
git clone git@github.com:apollographql/GitHunt-React.git cd GitHunt-React persistgraphql ui/graphql extracted_queries.json
客戶的實現方法可參考資料: 使用Apollo Client持久化GraphQL查詢