GraphQL vs REST API 架構,誰更勝一籌?
2015年, Facebook開源GraphQL 。 此后,它在前端Web中大受歡迎。 傳統的REST API有何不足?GraphQL優勢何在?在本文中, 我們將深入探討GraphQL的設計原則,比較 GraphQL 與 REST 的異同,并討論GraphQL 相對其他架構的優點。
1 你的 API 應該用哪項技術?
自從 2015 年 Facebook 開源 GraphQL 規范以來,它就在前端 Web 開發中迅速流行起來。
-
為什么這種新技術會突然流行起來?
-
與傳統 REST API 相比,GraphQL 提供了哪些優勢?
我們將討論 GraphQL 的設計原則,比較 GraphQL 與 REST 中的相同請求,并 深入探討 GraphQL 相對其他架構的優點 。
為理解 GraphQL 作為 API 架構的好處,我們要討論 API 在客戶端 - 服務器結構中的作用。API(應用程序編程接口)是一個中間層,它允許服務器從客戶端接收結構化數據請求,并針對請求的數據發送結構化的響應。設計 API 架構的方法有很多種。
讓我們來研究一下促使 GraphQL 適合現代化 Web 應用程序的重要基本設計原則。
2 GraphQL 服務器的設計原則
GraphQL 規范概括了 5 個設計原則,這使其成為現代前端開發的良好解決方案。 我們看一下 GraphQL 的設計原則,并以 Facebook 新聞推送作為我們的用例。
-
查詢為分層結構,使用將查詢與響應數據1對1匹配的分層和嵌套字段格式。查詢和響應的形狀類似于樹,可查詢每個項的其他嵌套字段。在 Facebook 的新聞推送中,這種結構允許一個查詢返回一個帖子列表、每個特定帖子的評論,以及每個評論的點贊。
-
該結構以產品為中心,關注前端希望如何接收數據,并構建交付所需的運行時。這使得 Facebook 的新聞推送可通過一次請求從后端獲取需要的所有數據,使服務器按照 GraphQL 的規范從不同的端點獲取數據。
-
它使用特定于應用程序的類型系統,該系統使開發人員能在執行前確保查詢使用了有效類型,并且語法正確。例如,新聞推送的 GraphQL 模式要求字段“user”必須包含一個字符串,而“likes”必須包含一個數字。如果查詢試圖添加不同類型的輸入,GraphQL 將在執行查詢前拋出一個錯誤。
-
GraphQL 查詢是在客戶端指定的,因此,客戶端確切知道它將以何種格式接收數據。這意味著,如果前端請求的格式是包含用戶名、評論和點贊的 post 數據,那么來自 Facebook 新聞推送的請求會構建在一個對象中,而不是像其他架構那樣構建多個單獨的數據塊。
-
使用 GraphQL 的服務器結構必須是內省的,或者可由 GraphQL 自己查詢。于是才有了像 GraphiQL 或 GraphQL playground 這樣的強大工具。這兩種工具都可以讓 Facebook 開發人員準確地看到在他們的服務器上使用了哪些查詢和字段。
為討論向 GraphQL 的轉變,以及這些設計原則如何給開發帶來好處。
我們首先深入了解傳統的 REST API 架構和它的不足之處。
3 傳統的 RESTful 架構
REST 架構的設計范式側重于分配 HTTP 請求方法(GET、POST、PUT、PATCH、DELETE)和 URL 端點之間的關系。
在 REST 架構中,方法和端點的每個組合得到不同的封裝功能。如果客戶端需要的數據特定端點 / 方法不提供,則可能需要額外請求。從 REST 請求返回的數據格式依賴于端點—不能保證這些數據會按照前端需要的方式進行格式化。為使用來自響應的數據(格式與缺省情況下從端點返回的格式不同),必須在客戶端編寫數據解析和數據操作。
接下來,讓我們看看 GraphQL 規范與 REST 的不同之處,以及它的優點。這些優點使這個新架構成為特別適合解決客戶端和服務器之間數據交付問題的解決方案。
4 GraphQL 架構
與 RESTful API 一樣,GraphQL API 設計用于處理 HTTP 請求并對這些請求提供響應。無論如何,這就是相似之處。REST API 構建在請求方法和端點之間的連接上,而 GraphQL API 被設計為只通過一個端點,始終使用 POST 請求進行查詢,其 URL 通常是 yourdomain.com/graphql。
請求到達 GraphQL 端點后,客戶端請求的載荷完全在請求體中處理。這個請求體必須遵循 GraphQL 規范,API 必須有適當的服務器端邏輯來處理這些請求并提供適當的響應。
這提供了比 RESTful API 更流暢的客戶端體驗,后者可能要求客戶端針對多個數據塊發出多個請求,并在數據返回后進行操作。
為了闡明 GraphQL 是如何實現這一點的,讓我們分解一下 GraphQL 服務器的結構。
5 GraphQL 服務器
啟用 GraphQL 邏輯的服務器端邏輯由定義了服務器功能的 Documents 組成。這些 Documents 包含可執行文件和類型系統定義。顧名思義,類型系統定義為每個數據字段定義可接受的類型和格式輸入及結果。
可執行文件包含要處理的可能的操作列表,其中包括操作類型(查詢、修改或訂閱)、操作名稱、要查詢或寫入的字段和一個選擇集,該選擇集準確定義了將從操作返回的數據。選擇集是 GraphQL 的最大價值所在——它們允許客戶端查詢特定的數據集并接收包含所請求信息的響應:不多不少。
- GET /graphql?query={ books(id:12) { authors { firstName, lastName } title, yearPublished, length }
- {
- Query { // operation type
- books (id:12) { // operation endpoint
- authors { // requested fields
- firstName
- lastName
- }
- title
- yearPublished
- }
- }
- }
接下來,我們將看下 GraphQL 中查詢的結構。
6 GraphQL 查詢解析
下面是一個結構化的 GraphQL 查詢,用于獲取特定書籍的數據,包括作者的姓和名
- GET /graphql?query={ books(id:12) { authors { firstName, lastName } title, yearPublished, length }
- {
- Query { // operation type
- books (id:12) { // operation endpoint
- authors { // requested fields
- firstName
- lastName
- }
- title
- yearPublished
- }
- }
- }
這一切都可以通過一個查詢由 GraphQL 服務器邏輯解析和處理完成。當把它與 REST 架構中相同結構的請求進行比較時,GraphQL 的優勢就開始顯現出來了。
讓我們看看下面的 REST 請求結構,然后重點討論其中的一些差異!
7 REST 請求解析
要向 REST API 發出相同的請求,客戶端首先需要向能夠返回圖書數據的端點發送一個請求,并將圖書 id 作為參數傳入:
- GET /books/12
這個請求可能會返回一個包含特定圖書所有數據的對象,例如:
- {
- "title" : "The Hitchhiker's Guide to the Galaxy",
- "authorID": 42,
- "yearPublished" : 1978,
- "length": 208,
- "genre": "Science Fiction"
- }
在我 們的例子里,與相同的 GraphQL 查詢相比,該響應有兩個缺點:
-
REST 響應包含類似 genre 這樣的額外數據,返回的信息超出了我們的需求。
-
REST 需要再發送一個請求來獲得我們實際上正在查找的數據:這個特定作者的所有書籍。
為了獲得這些數據,我們需要使用我們的 authorID 發出一個額外的請求:
- GET /authors/42
這個請求的響應應該包含我們正在查找的所有數據:
- {
- "firstName": "Douglas",
- "lastName": "Adams"
- }
現在我們已經有了需要的所有書籍和作者數據,響應解析由客戶端完成。現在,前端應用程序必須將來自不同端點的數據組合在一起,用于實現期望的功能。總的來說,與 REST API 相比,GraphQL 提供的性能優勢可以為前端開發人員帶來回報。使用 GraphQL 規范創建服務器可能需要更多的設置以及編寫預測性的服務器端邏輯來解析和處理請求。
雖然 GraphQL 的設置成本可能比傳統的 REST 架構要高,但是,更易于維護的代碼、健壯的開發工具和精簡的客戶端查詢所帶來的好處通常會超過成本。