GraphQL 規範對於處理網路、授權和分頁等 API 面臨的幾個重要問題刻意保持沉默。這並不表示使用 GraphQL 時沒有解決這些問題的方法,只是這些方法並未包含在 GraphQL 是什麼的說明中,而只是常見做法。
本節中的文章不應視為教條,在某些情況下,可以合理地忽略這些文章,而採用其他方法。有些文章介紹了 Facebook 在設計和部署 GraphQL 服務方面發展出的一些哲學,而另一些文章則是解決常見問題(例如透過 HTTP 提供服務和執行授權)的更具策略性的建議。
以下是 GraphQL 服務的一些較常見最佳實務和觀點的簡要說明,不過本節中的每篇文章都將更深入地探討這些和其他主題。
GraphQL 通常透過單一端點提供服務,該端點表達服務的完整功能。這與 REST API 形成對比,REST API 公開一組 URL,每個 URL 都公開單一資源。雖然 GraphQL 可以與一組資源 URL 一起使用,但這可能會讓它更難與 GraphiQL 等工具一起使用。
在 透過 HTTP 提供服務 中閱讀更多相關資訊。
GraphQL 服務通常使用 JSON 回應,但 GraphQL 規範 並不要求這樣做。JSON 對於承諾提供更佳網路效能的 API 層來說似乎是個奇怪的選擇,但由於它主要是文字,因此使用 GZIP 壓縮的效果非常好。
建議任何製作環境的 GraphQL 服務啟用 GZIP,並鼓勵其用戶端傳送標頭
Accept-Encoding: gzip
JSON 對用戶端和 API 開發人員來說也很熟悉,而且容易閱讀和除錯。事實上,GraphQL 語法部分受到 JSON 語法啟發。
雖然沒有任何因素會阻止 GraphQL 服務像其他 REST API 一樣進行版本控制,但 GraphQL 堅決主張避免版本控制,並提供工具讓 GraphQL 架構持續演進。
為什麼大多數 API 會進行版本控制?當對從 API 端點傳回的資料控制有限時,任何變更都可能被視為重大變更,而重大變更需要新的版本。如果新增功能到 API 需要新的版本,那麼就會在頻繁發布和擁有許多增量版本,與 API 的可理解性和可維護性之間產生取捨。
相反地,GraphQL 只傳回明確要求的資料,因此可以透過新的類型和這些類型上的新欄位新增新功能,而不會造成重大變更。這導致了始終避免重大變更和提供無版本 API 的常見做法。
大多數辨識「null」的類型系統同時提供一般類型和該類型的可為 null版本,其中預設類型不包含「null」,除非明確宣告。然而,在 GraphQL 類型系統中,每個欄位預設為可為 null。這是因為在由資料庫和其他服務支援的網路服務中,可能會發生許多問題。資料庫可能會當機、非同步動作可能會失敗、可能會擲回例外狀況。除了系統故障之外,授權通常可以是細緻的,其中要求中的個別欄位可以有不同的授權規則。
透過將每個欄位預設為可為 null,任何這些原因都可能導致僅該欄位傳回「null」,而不是讓要求完全失敗。相反地,GraphQL 提供類型的不可為 null變體,向客戶保證如果要求,欄位絕不會傳回「null」。相反地,如果發生錯誤,前一個父欄位將會是「null」。
在設計 GraphQL 架構時,重要的是要記住所有可能出錯的問題,以及「null」是否為失敗欄位的適當值。通常是,但偶爾不是。在這些情況下,請使用不可為 null 類型來提供該保證。
GraphQL 類型系統允許某些欄位傳回值清單,但將較長值清單的分頁留給 API 設計者。針對分頁有廣泛的可能 API 設計,每種設計都有優缺點。
通常可以傳回長清單的欄位會接受參數「first」和「after」,以允許指定清單的特定區域,其中「after」是清單中每個值的唯一識別碼。
最終,使用功能豐富的分頁設計 API 導致一種稱為「連線」的最佳實務模式。某些 GraphQL 的客戶端工具,例如 Relay,知道連線模式,並且當 GraphQL API 使用此模式時,可以自動提供對客戶端分頁的支援。
在 分頁 文章中深入了解此主題。
GraphQL 的設計方式讓您可以在伺服器上撰寫乾淨的程式碼,其中每個類型上的每個欄位都有用於解析該值的專注單一用途函數。不過,如果沒有額外的考量,一個天真的 GraphQL 服務可能會非常「健談」或重複從資料庫載入資料。
這通常透過批次處理技術來解決,其中在短時間內收集多個來自後端的資料要求,然後使用像 Facebook 的 DataLoader 等工具,以單一要求傳送至基礎資料庫或微服務。