GraphQL LogoGraphQL

GraphQL 最佳實務

GraphQL 規範對於處理網路、授權和分頁等 API 面臨的幾個重要問題刻意保持沉默。這並不表示使用 GraphQL 時沒有解決這些問題的方法,只是這些方法並未包含在 GraphQL 是什麼的說明中,而只是常見做法。

本節中的文章不應視為教條,在某些情況下,可以合理地忽略這些文章,而採用其他方法。有些文章介紹了 Facebook 在設計和部署 GraphQL 服務方面發展出的一些哲學,而另一些文章則是解決常見問題(例如透過 HTTP 提供服務和執行授權)的更具策略性的建議。

以下是 GraphQL 服務的一些較常見最佳實務和觀點的簡要說明,不過本節中的每篇文章都將更深入地探討這些和其他主題。

HTTP#

GraphQL 通常透過單一端點提供服務,該端點表達服務的完整功能。這與 REST API 形成對比,REST API 公開一組 URL,每個 URL 都公開單一資源。雖然 GraphQL 可以與一組資源 URL 一起使用,但這可能會讓它更難與 GraphiQL 等工具一起使用。

透過 HTTP 提供服務 中閱讀更多相關資訊。

JSON(含 GZIP)#

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 等工具,以單一要求傳送至基礎資料庫或微服務。

繼續閱讀 →以圖形思考