2015 年 9 月 14 日 by 李拜倫
當我們建置 Facebook 的行動應用程式時,我們需要一個資料擷取 API,它必須強大到足以描述所有 Facebook,但又簡單且易於學習,以便產品開發人員可以專注於快速建置應用程式。我們在三年前開發了 GraphQL 來滿足此需求。現在,它每天支援數千億次的 API 呼叫。今年,我們已開始透過起草規格、釋出參考實作,以及在 graphql.org 這裡建立社群,來開放 GraphQL 的原始碼。
早在 2012 年,我們就開始著手重建 Facebook 的原生行動應用程式。
當時,我們的 iOS 和 Android 應用程式只是我們行動網站檢視畫面的薄弱包裝。儘管這讓我們接近「一次撰寫,到處執行」行動應用程式的柏拉圖理想,但實際上,它卻讓我們的行動網頁檢視應用程式超出其限制。隨著 Facebook 的行動應用程式變得更複雜,它們的效能不佳,而且經常崩潰。
當我們轉換為原生實作的模型和檢視時,我們發現自己第一次需要新聞動態的 API 資料版本,而在此之前,新聞動態只以 HTML 形式傳遞。我們評估了將新聞動態資料傳遞給我們的行動應用程式的選項,包括 RESTful 伺服器資源和 FQL 資料表(Facebook 類似 SQL 的 API)。我們對於我們想在應用程式中使用的資料與他們所需的伺服器查詢之間的差異感到沮喪。我們不會以資源 URL、次要金鑰或關聯資料表的形式思考資料;我們會以物件圖表和我們最終在應用程式中使用的模型(例如 NSObjects 或 JSON)的形式思考資料。
在伺服器上撰寫準備資料的程式碼,以及在用戶端撰寫剖析資料的程式碼,這兩部分的程式碼量也很可觀。這種沮喪激勵我們當中幾個人開始這個專案,最終成為 GraphQL。GraphQL 是我們從產品設計師和開發人員的角度重新思考行動應用程式資料擷取的機會。它將開發重點轉移到用戶端應用程式,設計師和開發人員會在那裡花費時間和注意力。
GraphQL 查詢是一個字串,會傳送到伺服器進行詮釋和執行,然後再將 JSON 傳回用戶端。
定義資料形狀:您會首先注意到 GraphQL 查詢會反映其回應。這使得預測查詢所傳回資料的形狀,以及在您知道應用程式所需資料時撰寫查詢,變得容易。更重要的是,這使得 GraphQL 非常容易學習和使用。GraphQL 毫不避諱地由產品的資料需求,以及建立這些產品的設計人員和開發人員所驅動。
階層式:GraphQL 的另一個重要面向是其階層式性質。GraphQL 自然會遵循物件之間的關係,而 RESTful 服務可能需要多次往返(在行動網路中會消耗大量資源)或在 SQL 中使用複雜的聯結陳述式。此資料階層與圖形結構資料儲存庫搭配得很好,最終也會與其所使用的階層式使用者介面搭配得很好。
強類型:GraphQL 查詢的每個層級都對應到特定類型,而每個類型都會描述一組可用的欄位。這與 SQL 類似,它讓 GraphQL 能在執行查詢之前提供描述性錯誤訊息。它也能與 Obj-C 和 Java 的強類型原生環境搭配得很好。
通訊協定,而非儲存:伺服器上的每個 GraphQL 欄位都由一個函式支援,此函式會連結到應用程式層級的程式碼。當我們建置 GraphQL 來支援新聞動態時,我們已經有一個精密的動態排名和儲存模型,以及現有的資料庫和商業邏輯。GraphQL 必須利用所有這些現有工作才能發揮作用,因此不會指示或提供任何後端儲存。相反地,GraphQL 透過公開您的應用程式層級(而非儲存層級)來利用您現有的程式碼。
內省:可以查詢 GraphQL 伺服器以取得它支援的類型。這會為工具和用戶端軟體建立一個強大的平台,以建立在這些資訊之上,例如在靜態類型語言中產生程式碼、我們的應用程式架構 Relay,或像 GraphiQL(如下圖所示)的 IDE。GraphiQL 能協助開發人員快速學習和探索 API,而無需搜尋程式碼庫或與 cURL 糾纏不清。
版本免費:傳回資料的形狀完全由客戶端查詢決定,因此伺服器變得更簡單且易於概括。當您新增產品功能時,可以將其他欄位新增至伺服器,而不會影響現有客戶端。當您淘汰舊功能時,對應的伺服器欄位可以標示為已棄用,但仍繼續運作。這個漸進的向下相容程序消除了遞增版本號碼的需求。我們仍然在單一版本的 GraphQL API 上支援三年已發行的 Facebook 應用程式。
有了 GraphQL,我們得以在 2012 年於 iOS 上建置功能齊全的原生新聞動態,並在不久後於 Android 上建置。從那時起,GraphQL 已成為我們建置行動應用程式及其驅動伺服器的主要方式。三年多來,GraphQL 驅動了我們行動應用程式中幾乎所有資料擷取,每秒處理來自近 1,000 個已發行的應用程式版本的數百萬個要求。
當我們在 2012 年建置 GraphQL 時,我們不知道它對我們在 Facebook 建置事物的方式會變得如此重要,也沒有預期到它在 Facebook 以外的價值。然而,今年稍早我們宣布了 Relay,這是我們建立在 GraphQL 之上的網頁和 React Native 應用程式架構。社群對 Relay 的熱情激勵我們重新檢視 GraphQL,以評估每個細節、進行改善、修正不一致之處,並撰寫說明 GraphQL 及其運作方式的規格。
兩個月前,我們公開我們的進度,並發布了GraphQL 規格的工作草案和參考實作:GraphQL.js。自此之後,一個社群開始圍繞 GraphQL 而形成,而 GraphQL 執行時期的版本正在以許多語言建置,包括 Go、Ruby、Scala、Java、.Net 和 Python。我們也開始分享我們在內部使用的部分工具,例如GraphiQL,一個瀏覽器內 IDE、文件瀏覽器和查詢執行器。GraphQL 也在 Facebook 外部看到實際應用,在顧問公司Red Badger為Financial Times執行的一個專案中。
「GraphQL 讓資料擷取的協調變得更簡單,而且它幾乎可以作為前端和後端之間一個完美的隔離點。」— Red Badger 軟體工程師 Viktor Charypar
雖然 GraphQL 已成為 Facebook 產品開發中既定的一部分,但其在 Facebook 以外的使用才剛開始。試用 GraphiQL,並協助提供對我們的 規格 的回饋。我們認為 GraphQL 能大幅簡化客戶端產品開發人員和伺服器端工程師的資料需求,不論在任一環境中使用哪種語言,我們很興奮能持續改善 GraphQL,協助社群在 GraphQL 周圍成長,並期待我們能共同打造出什麼。