GraphQL 學習筆記

本文未完成,持續更新中

前言

GraphQL1 是一個由 Facebook 制定的查詢語言,它可以被用來取代 RESTful2 API 溝通上。

從 RESTful 到 GraphQL

傳統的 RESTful API,使用簡單的規則將資源定位,例如下面可以用來抓取一個使用者的資源:

GET /users/1

也可以配合 HTTP 動詞3 來對資源進行操作,例如下面可以用來建立一個新的群組資源:

POST /groups

當然,RESTful 也可以簡單的抓取一個群組裡面的使用者清單:

GET /groups/1/users

但是,人生就是這個但是,如果你想抓取某個群組裡面的使用者清單以外,還想要抓取裡面的使用者的資料呢?

通常,RESTful 會在 API 裡面返回部分的使用者資料,但我們遇到需要其他資料的時候,最常見的解法有兩種:

從 Client 端下手

簡單來說就讓 Client 送多次的請求,這辦法會遇到類似 N+1 的問題,因為其實 RESTful 並沒有指出該如何對複數資源進行操作(包含抓取跟修改、刪除),送出的請求如下:

GET /groups/1/users

{
    "users": [
        {
            "id": 1,
            "name": "Bob"
        },
        {
            "id": 2,
            "name": "Alice"
        },
        {
            "id": 3,
            "name": "Katherine"
        }
    ]
}

GET /users/1

{
    "id": 1,
    "name": "Bob",
    "email": "[email protected]",
    "url": "http://bob.example.com"
}

GET /users/2

{
    "id": 2,
    "name": "Alice",
    "email": "[email protected]",
    "url": "http://alice.example.com"
}

GET /users/3

{
    "id": 3,
    "name": "Katherine",
    "email": "[email protected]",
    "url": "http://kathy.example.com"
}

這個方法的缺點就是在連線延遲或網路品質不好的狀況下,可能要花比較多的時間或次數來完成。

從 Server 端下手

最簡單的做法就是接受在 Query 裡面加上 users.detail=1,Server 瞭解請求之後直接回覆完整的 user 資料:

GET /groups/1/users?users.detail=1

{
    "users": [
        {
            "id": 1,
            "name": "Bob",
            "email": "[email protected]",
            "url": "http://bob.example.com"
        },
        {
            "id": 2,
            "name": "Alice",
            "email": "[email protected]",
            "url": "http://alice.example.com"
        },
        {
            "id": 3,
            "name": "Katherine",
            "email": "[email protected]",
            "url": "http://kathy.example.com"
        }
    ]
}

缺點就是需要因狀況而修改 Server API 的程式碼。而且單一請求的吞吐量很容易會因為一次將所有資料全數返回,導致大量暴增。

RESTful 的缺點

從上面的例子就可以看到 RESTful 在現今有一些缺點,例如:

  • 沒辦法處理批次請求(沒有規範);
  • 沒辦法由 Client 指定返回欄位,導致大部分資源被浪費;
  • 無限增長的 endpoint 數量,每多一種資源/處理資源的方式,就會多一系列相關的 endpoint;
  • 無法很好的處理巢狀資源。

GraphQL 的特點

而 GraphQL 提出了以下的特點,強化了傳統 RESTful API 辦不到的事情以及給予更大的彈性:

  • 型別系統 —— GraphQL 是強型別語言,對於所有返回的物件,其型別都必須被預先定義;
  • 內省機制(Introspection) —— 能夠藉由查詢內部結構讓 client 輕易掌握 API 細節;
  • 提供巢狀資源以及批次請求的支援;
  • 由 Client 指定返回欄位,降低連線負載度。

預覽 GraphQL

在看了上面的介紹之後,相信大家還是對 GraphQL 一頭霧水才對,接下來就上面的例子,我們可以看看 GraphQL 的版本之後再一一介紹:

query {
    group(id: 1) {
        users {
            id
            email
        }
    }
}
{
    "data": {
        "group": {
            "users": [
                {
                    "id": 1,
                    "email": "[email protected]"
                },
                {
                    "id": 2,
                    "email": "[email protected]"
                },
                {
                    "id": 3,
                    "email": "[email protected]"
                }
            ]
        }
    }
}
因主題更新,留言功能暫時停用中。