如何選擇 REST 還是 GraphQL

在本文中,簡單比較 REST 和 GraphQL 的優(yōu)點和缺點,以便您可以決定哪種 API 架構(gòu)最適合您的項目
當(dāng)我們要創(chuàng)建數(shù)據(jù)驅(qū)動的 Web 或移動應(yīng)用程序,需要開發(fā)后臺 API,通過它可以從后端服務(wù)器來訪問或操作數(shù)據(jù)。目前最流行的 API 架構(gòu)是 REST,盡管 REST 廣為人知并且通常易于使用,但它也有一些缺點,主要是包括冗余數(shù)據(jù)的過度獲取、擴展效率低下。
GraphQL 是一種新型 API 架構(gòu),其設(shè)計比 REST 更靈活、更高效,具有聲明式數(shù)據(jù)獲取等功能。雖然 GraphQL 已經(jīng)變得相當(dāng)流行,但它并沒有取代 REST,因為一些用戶發(fā)現(xiàn)它更難使用,并認(rèn)為它是一個過度設(shè)計的解決方案,特別是對于較小的應(yīng)用程序來說。
在本文中,將深入探討 REST 和 GraphQL 的優(yōu)缺點,以便您可以決定哪種 API 架構(gòu)最適合您的項目。
REST
當(dāng)前應(yīng)用程序開發(fā)中 API 的主流架構(gòu)是 REST,大多數(shù)后端框架將實現(xiàn) REST。REST API 通常使用 HTTP 方法通過稱為(例如GET /api/articles )的 URL 集合進行調(diào)用POST /api/articles。
Demo
以創(chuàng)建一個博客網(wǎng)站為例。在主頁上,顯示最新文章的摘要,包括標(biāo)題、圖像和簡短說明。要為此提供數(shù)據(jù),需要在后端服務(wù)器上設(shè)置一個 REST API,GET/api/articles它將以 JSON 數(shù)組的形式返回所需的數(shù)據(jù),如下例所示:
// GET /articles
[
  {
    "id": 1,
    "title": "REST is Awesome",
    "image": "https://myrestblog.com/img/dsh9a89.png",
    "description": "The benefits of REST"
  },
  {
    "id": 2,
    "title": "How REST Works",
    "image": "https://myrestblog.com/img/33szad2.png",
    "description": "Learn about REST"
  }
]REST優(yōu)點
REST 在很大程度上擊敗了 SOAP、WebService、XML 等較舊的 API 協(xié)議,并且盡管出現(xiàn)了 GraphQL 等較新的替代方案,但仍繼續(xù)流行,其主要原因為:
易于實施
在 Web 服務(wù)器應(yīng)用程序中設(shè)置 REST 很簡單,尤其是當(dāng)它使用 Java的 Springcloud或 Python 的 Requests 等 API 框架時。例如,使用 MongoDB 在 Express 應(yīng)用程序中設(shè)置 REST 端點/articles就像調(diào)用數(shù)據(jù)庫并將記錄返回為 JSON 一樣簡單,如下所示:
python:
app.get('/api/articles', async (req, res) => {
    try {
        const articles = await db.articles.find() res.json(articles)
    } catch (err) {
        res.status(500).send(err)
    }
})廣泛理解和協(xié)同開發(fā)
無論 GraphQL 是否優(yōu)于 REST,大多數(shù)開發(fā)人員都會同意,當(dāng)您使用自己所知道的知識時,開發(fā)效率會更高。截至 2022 年,如果您有多個開發(fā)人員在開發(fā)您的應(yīng)用程序,或者您有公共 API,則大多數(shù)消費者將熟悉 REST,GraphQL 還不能說同樣的情況,哈哈~~。
REST 的缺點
要理解為什么創(chuàng)建 GraphQL,我們需要首先看看 REST 的缺點
過度獲取
回到博客的示例,假設(shè)創(chuàng)建了一個移動網(wǎng)站。與桌面版本一樣,在主頁上顯示文章摘要。由于手機屏幕較小,這里的摘要只需要標(biāo)題和圖片,可以省略描述。不幸的是,由于GET /api/articles端點是固定的,移動版本description在調(diào)用 API 時仍然會收到該字段。這種低效率被稱為“過度獲取”,并且在發(fā)送大量數(shù)據(jù)時會成為挑戰(zhàn)。
冗余數(shù)據(jù)效率低下
當(dāng)對象包含表示相關(guān)實體的子對象時,該對象具有嵌套數(shù)據(jù)。例如,可能有一個帶有嵌套評論對象的文章對象。由于實體在 REST 中被分配了自己唯一的URL,因此可能需要通過單獨的 API 往返來填充嵌套數(shù)據(jù)。
例如,要獲取一篇文章,我們首先使用端點GET /api/articles。要獲取本文的評論,我們需要首先等待文章數(shù)據(jù)填充,以便我們知道在后續(xù)請求中需要獲取哪些特定評論,如下面的代碼示例所示。等待這些后續(xù)請求得到解決將增加用戶在與頁面交互之前必須等待的時間。
// GET /articles
[
  {
    "id": 1,
    "title": "REST is Awesome",
    "image": "https://myrestblog.com/img/dsh9a89.png",
    "description": "An article about REST",
    "comment_ids": [
      10,
      14,
      22
    ]
  },
  { ... }
]GraphQL
REST 的低效率促使 Facebook 工程師在 2015 年創(chuàng)建了一種新的 API 設(shè)計,稱為 GraphQL。GraphQL 迅速成為開發(fā)人員和公司的熱門選擇,推出了相關(guān)工具和服務(wù)的生態(tài)系統(tǒng)。與 REST 一樣,GraphQL 不是一個特定的軟件,而是 API 設(shè)計的規(guī)范。
GraphQL 工作原理
為了了解 GraphQL 的優(yōu)勢,快速概述它的工作原理。與 REST 不同,GraphQL 需要一個架構(gòu)來告訴客戶端和服務(wù)器允許通過 API 執(zhí)行哪些數(shù)據(jù)和操作。它們是使用 GraphQL 模式語言定義的——一種與語言無關(guān)的簡單格式,具有強大的類型系統(tǒng)。
Demo
Article讓我們回到具有和實體的博客網(wǎng)站的示例Comment。在我們的 GraphQL 模式中,我們定義Article具有必需的整數(shù)id字段和title、image、 和的可選字符串字段的類型description,如下所示:
type Article {
  id: Integer!
  title: String
  image: String
  description: String
}除了基本標(biāo)量類型之外,模式對象還可以相互引用。Article例如,我們可以在類型和類型之間創(chuàng)建一對多關(guān)系Comment,如下所示:
type Article {
  id: Integer!
  title: String
  image: String
  description: String
  comments: [Comment]
}
type Comment {
  content: String
  article: Article
  author: Author
}模型定義
GraphQL 模式的另一個重要用途是定義操作,其中包括讀取數(shù)據(jù)的查詢和寫入數(shù)據(jù)的突變。在這里,我們提供了 的查詢Articles,其類型為文章數(shù)組:
type Article {
  id: Integer!
  title: String
  image: String
  description: String
  comments: [Comment]
}
type Comment {
  content: String
  article: Article
  author: Author
}
type Query {
  articles: [Article]
}GraphQL 的優(yōu)點
通過對 GraphQL 的基本了解,我們現(xiàn)在可以了解它的主要優(yōu)點。
聲明式數(shù)據(jù)獲取
GraphQL 的殺手級功能是聲明式數(shù)據(jù)獲取,客戶端可以準(zhǔn)確指定其需要的數(shù)據(jù)。這可以包括特定字段,甚至在嵌套對象內(nèi)。我們之前看到,操作必須在模式上定義。不過,在這些操作中,我們可以指定希望查詢返回哪些字段(最多達(dá)到架構(gòu)的限制)。
例如,我們可以創(chuàng)建一個查詢來Articles僅獲取我們想要的字段,無論是否有嵌套Comments。請參閱下面的示例:
query {
  articles {
    id
    title
    image
    description
    comments {
      content
    }
  }
}這是將從該查詢返回的數(shù)據(jù)結(jié)構(gòu)。請注意,GraphQL 響應(yīng)中收到的數(shù)據(jù)將與請求它的查詢具有相同的形狀。
{
  "data": {
    "articles": [
      {
        "id": 1,
        "title": "REST is Awesome",
        "image": "https://restblog.com/img/dsh9a8.png",
        "description": "An article about REST",
        "comments": [
          {
            "content": "GraphQL is better!"
          },
          { ... }
        ]
      }
    ],
    ...
  }
}通過這種方式,GraphQL 消除了過度獲取和對嵌套數(shù)據(jù)的順序調(diào)用的需要。
魯棒性
由于強類型化和預(yù)定義查詢的要求,GraphQL 可以提供開箱即用的驗證和類型檢查。反過來,這意味著 GraphQL 本質(zhì)上是自記錄的。一旦字段、類型或查詢發(fā)生變化,基于模式的文檔就可以自動更新。
版本控制
每次應(yīng)用程序發(fā)生變化時,API 也可能需要更改。例如,假設(shè)我們決定將實體description中的字段重命名Article為blurb. REST 通過提供多個版本來處理這個問題,例如/api/v1,api/v2這對于 API 開發(fā)人員和消費者來說都是很麻煩的。使用 GraphQL,可以從架構(gòu)中刪除已棄用的字段,而不會影響現(xiàn)有查詢。這為應(yīng)用程序提供了對新功能的持續(xù)訪問,并鼓勵更清潔、更易于維護的服務(wù)器代碼。
GraphQL 的缺點
雖然 GraphQL 為 REST 的缺點提供了一個優(yōu)雅的解決方案,但請考慮一下 GraphQL 面臨的一些批評。
取舍權(quán)衡困惑
一些開發(fā)人員認(rèn)為 GraphQL 正在解決的問題常常被夸大了。例如,對于大多數(shù)小型應(yīng)用程序來說,如果過度獲取的幾個字節(jié)的數(shù)據(jù)進入有效負(fù)載,這可能并不重要。
更難合作
另一個批評是 GraphQL 實現(xiàn)最終比 REST 更難編碼,它還為新用戶提供了更困難的學(xué)習(xí)曲線。
難以緩存
最后,GraphQL 經(jīng)常因更難以緩存而受到批評,REST 客戶端可以獲得 HTTP 緩存的好處,因為所有端點都是 URL,而 GraphQL 客戶端需要實現(xiàn)自己的自定義解決方案,如使用本地緩存,譬如redux-persit、localforage
結(jié)論
雖然 REST 架構(gòu)在過去十年中主導(dǎo)了 Web 開發(fā),但它對設(shè)置端點的使用使其有些不靈活且低效。GraphQL 通過提供嚴(yán)格類型的模式語言來解決這些問題,消費者可以根據(jù)需要進行查詢。















 
 
 













 
 
 
 