[譯] 我常常聽到的 GraphQL 究竟是什麼?

我常常聽到的 GraphQL 究竟是什麼?

當據說出了一門新技術的時候,你可能會和我同樣有如下 3 種反應:javascript

1. 嫌棄

又來一個 JavaScript 類庫?反正我只用 JQuery 就好了。前端

2. 感興趣

嗯,也許我應該去了解一下這個我老是聽別人說到的新庫。java

3. 恐慌

救命啊!我必須立刻去學這個新庫,不然我就會被淘汰了!node

在這個迅速發展的時代,讓你保持理智的方法就是保持上述第二或第三種態度去學一些新的知識,走在潮流以前的同時激起你的興趣。react

所以,如今就是學習 GraphQL 這個你經常聽到別人談論的東西的最好時機!android

基礎

簡單的說,GraphQL 是一種描述請求數據方法的語法,一般用於客戶端從服務端加載數據。GraphQL 有如下三個主要特徵:ios

  • 它容許客戶端指定具體所需的數據。
  • 它讓從多個數據源彙總取數據變得更簡單。
  • 它使用了類型系統來描述數據。

如何入門 GraphQL 呢?它實際應用起來是怎樣的呢?你如何開始使用它呢?要找到以上問題的答案,請繼續閱讀吧!git

遇到的問題

GraphQL 是由 Facebook 開發的,用於解決他們巨大、老舊的架構的數據請求問題。可是即便是比 Facebook 小不少的 app,也一樣會碰上一些傳統 REST API 的侷限性問題。github

例如,假設你要展現一個文章(posts)列表,在每篇文章的下面顯示喜歡這篇文章的用戶列表(likes),其中包括用戶名和用戶頭像。這個需求很容易解決,你只須要調整你的 posts API 請求,在其中嵌入包括用戶對象的 likes 列表,以下所示:web

可是如今你是在開發移動 app,加載全部的數據明顯會下降 app 的速度。因此你得請求兩個接口(API),一個包含了 likes 的信息,另外一個不含這些信息(只含有文章信息)。

如今咱們再摻入另外一種狀況:posts 數據是由 MySQL 數據庫存儲的,而 likes 數據倒是由 Redis 存儲的。如今你該怎麼辦?

按着這個劇本想想 Facebook 的客戶端有多少個數據源和 API 須要管理,你就知道爲何如今評價很好的 REST API 所體現出的侷限性了。

解決的方案

Facebook 提出了一個概念很簡單的解決方案:再也不使用多個「愚蠢」的節點,而是換成用一個「聰明」的節點來進行復雜的查詢,將數據按照客戶端的要求傳回。

實際上,GraphQL 層處於客戶端與一個或多個數據源之間,它接收客戶端的請求而後根據你的設定取出須要的數據。仍是不明白嗎?讓咱們打個比方吧!

以前的 REST 模型就好像你預約了一塊披薩,而後又要叫便利店送一些日用品上門,接着打電話給乾洗店去取衣服。這有三個商店,你就得打三次電話。

GraphQL 從某方面來講就像是一個私人助理:你只須要給它這三個店的地址,而後簡單地告訴它你須要什麼 (「把我放在乾洗店的衣服拿來,而後帶一塊大號披薩,順便帶兩個雞蛋」),而後坐着等他回來就好了。

換句話說,爲了讓你能和這個神奇的私人助手溝通,GraphQL 創建了一套標準的語言。

上圖是 Google 圖片找的,有的私人助理甚至有八條手臂。

理論上,一個 GraphQL API 主要由三個部分組成:schema(類型)queries(查詢) 以及 resolvers(解析器)

查詢(Queries)

你向你的 GraphQL 私人助理提出的請求就是 query ,query 的形式以下所示:

query {
  stuff
}複製代碼

在這裏,咱們用 query 關鍵字定義了一個新的查詢,它將取出名叫 stuff 的字段。GraphQL 查詢(Queries)最棒之處就是它支持多個字段嵌套查詢,咱們能夠在上面的基礎上加深一個層級:

query{
  stuff {
    eggs
    shirt
    pizza
  }
}複製代碼

正如你所見,客戶端在查詢的時候不須要關心數據是來自於哪個「商店」的。你只須要請求你要的數據,GraphQL 服務端將會完成其它全部的工做。

還有一點值得注意,query 字段也能夠指向一個數組。例如,如下是一個查詢一個文章列表的經常使用模式:

query {
  posts { # this is an array
    title
    body
    author { # we can go deeper!
      name
      avatarUrl
      profileUrl
    }
  }
}複製代碼

Query 字段也支持使用參數。若是我想展現一篇特別的文章,我能夠將 id 參數放在 post 字段中:

query {
  post(id: "123foo"){
    title
    body
    author{
      name
      avatarUrl
      profileUrl
    }
  }
}複製代碼

最後,若是我想讓 id 參數能動態改變,我能夠定義一個變量,而後在 query 字段中重用它。(請注意,咱們在 query 字段處也要定義一次這個變量的名字)

query getMyPost($id: String) {
  post(id: $id){
    title
    body
    author{
      name
      avatarUrl
      profileUrl
    }
  }
}複製代碼

有個很好的方式來實踐這些方法:使用 GitHub’s GraphQL API Explorer 。例如,你能夠嘗試下面的查詢:

query {
  repository(owner: "graphql", name: "graphql-js"){
    name
    description
  }
}複製代碼

GraphQL 的自動補全功能

當你嘗試在下面輸入一個名爲 description 的新字段名時,你可能會注意到 IDE 會根據 GraphQL API 將可選的字段名自動補全。真棒!

The Anatomy of a GraphQL Query

你能夠讀讀這篇超棒的文章《Anatomy of a GraphQL Query》,瞭解更多 GraphQL 查詢的知識。

解釋器(Resolvers)

除非你給他們地址,不然即便是這個世界上最好的私人助理也不能去拿到乾洗衣物。

一樣的,GraphQL 服務端並不知道要對一個即將到來的查詢作什麼處理,除非你使用 resolver 來告訴他。

一個 resolver 會告訴 GraphQL 在哪裏以及如何去取到對應字段的數據。例如,下面是以前咱們取出 post 字段例子的 resolver(使用了 Apollo 的 GraphQL-Tools ):

Query: {
  post(root, args) {
    return Posts.find({ id: args.id });
  }
}複製代碼

在這個例子中,咱們將 resolver 放在 Query 中,由於咱們想要直接在根層級查詢 post。但你也能夠將 resolver 放在子字段中,例如查詢 post(文章)的 author(做者)字段能夠按照下面的形式:

Query: {
  post(root, args) {
    return Posts.find({ id: args.id });
  }
},
Post: {
  author(post) {
    return Users.find({ id: post.authorId})
  }
}複製代碼

還有,resolver 不只僅只能返回數據庫裏的內容,例如,若是你想爲你的 Post 類型加上一個 commentsCount(評論數量)屬性,能夠這麼作:

Post: {
  author(post) {
    return Users.find({ id: post.authorId})
  },
  commentsCount(post) {
    return Comments.find({ postId: post.id}).count() 
  }
}複製代碼

理解這裏的關鍵在於:對於 GraphQL,你的 API 結構與你的數據庫結構是解耦的。換一種說法,咱們的數據庫中可能根本就沒有 authorcommentsCount 這兩個字段,可是咱們能夠經過 resolver 的力量將它們「模擬」出來。

正如你所見,咱們能夠在 resolver 中寫任何你想寫的代碼。所以,你能夠經過改變 resolver 任意地修改數據庫中的內容,這種形式也被稱爲 mutation resolver。

類型(Schema)

GraphQL 的類型結構系統可讓不少事情都變得可行。我今天的目標僅僅是給你作一個快速的概述而不是詳細的介紹,因此我不會在這個內容上繼續深刻。

話雖如此,若是你想了解更多這方面的信息,我建議你閱讀 GraphQL 官方文檔

常見問題

讓咱們先暫停,回答一些常見的問題。

你確定想問一些問題,來吧,儘管問別害羞!

GraphQL 與圖形數據庫有什麼關係?

它們真的沒有關係,GraphQL 與諸如 Neo4j 之類的圖形數據庫沒有任何關係。名稱中的 「Graph」 是來自於 GraphQL 使用字段與子字段來遍歷你的 API 圖譜;「QL」 的意思是「查詢語言」(query language)。

我用 REST 用的很開心,爲何我要切換成 GraphQL 呢?

若是你使用 REST 尚未碰上 GraphQL 所解決的那些痛點,那固然是件好事啦!

可是使用 GraphQL 來代替 REST 基本不會對你 app 的用戶體驗產生任何影響,因此「切換」這件事並非所謂「生或死」的抉擇。話雖如此,我仍是建議你若是有機會的話,先在項目裏小範圍地嘗試一下 GraphQL 吧。

若是我不用 React、Relay 等框架,我能使用 GraphQL 嗎?

固然能!由於 GraphQL 僅僅是一個標準,你能夠在任何平臺、任何框架中使用它,甚至在客戶端中也一樣能應用它(例如,Apollo 有針對 web、iOS、Angular 等環境的 GraphQL 客戶端)。你也能夠本身去作一個 GraphQL 服務端。

GraphQL 是 Facebook 作的,可是我不信任 Facebook

再強調一次,GraphQL 只是一個標準,這意味着你能夠在不用 Facebook 一行代碼的狀況下實現 GraphQL。

而且,有 Facebook 的支持對於 GraphQL 生態系統來講是一件好事。關於這塊,我相信 GraphQL 的社區足夠繁榮,即便 Facebook 中止使用 GraphQL,GraphQL 依然可以茁壯成長。

「讓客戶端本身請求須要的數據」這整件事情聽起來彷佛不怎麼安全……

你得本身寫本身的 resolver,所以在這個層面上是否會出現安全問題徹底取決於你。

例如,爲了防止客戶端一遍又一遍地請求查詢記錄形成 DDOS 攻擊,你可讓客戶端指定了一個 limit 參數去控制它接受數據的數量。

那麼我如何上手 GraphQL?

一般來講,一個 GraphQL 驅動的 app 起碼須要如下兩個組件:

  • 一個 GraphQL 服務端 來爲你的 API 提供服務。
  • 一個 GraphQL 客戶端 來鏈接你的節點。

瞭解更多可用的工具,請繼續閱讀。

如今你應該對 GraphQL 有了一個恰當的認識,下面讓咱們來介紹一下 GraphQL 的主要平臺與產品。

GraphQL 服務端

萬丈高樓平地起,蓋起這棟樓的第一塊磚就是一個 GraphQL 服務端。 GraphQL 它自己僅僅是一個標準,所以它敞開大門接受各類各樣的實現。

GraphQL-JS (Node)

它是 GraphQL 的最初的實現。你能夠將它和 express-graphql 一塊兒使用,建立你本身的 API 服務

GraphQL-Server (Node)

Apollo 團隊也有他們本身的一站式 GraphQL 服務端實現。它雖然尚未像 GraphQL-JS 同樣被普遍使用,可是它的文檔、支持都作得很棒,使用它能快速取得進展。

其它平臺

GraphQL.org 列了一個清單: GraphQL 在其它平臺下的實現清單 (包括 PHP、Ruby 等)。

GraphQL 客戶端

雖然你不使用客戶端類庫也能夠很好地查詢 GraphQL API,可是一個相對應的客戶端類庫將會讓你的開發更加輕鬆

Relay

Relay 是 Facebook 的 GraphQL 工具。我還沒用過它,可是我據說它主要是爲了 Facebook 本身的需求量身定作的,可能對大多數的用戶來講不是那麼人性化。

Apollo Client

在這個領域的最新參賽者是 Apollo,它正在迅速發展。典型的 Apollo 客戶端技術棧由如下兩部分組成:

另外,在默認的狀況下 Apollo 客戶端使用 Redux 存儲數據。這點很棒,Redux 自己是一個有着豐富生態系統的超棒的狀態管理類庫。

Apollo 在 Chrome 開發者工具中的插件

開源 App

雖然 GraphQL 還屬於新鮮事物,可是它已經被一些開源 app 使用了。

VulcanJS

首先我得聲明一下,我是 VulcanJS 的主要維護者。我建立 VulcanJS 是爲了讓人們在不用寫太多樣板代碼的狀況下充分享受 React、GraphQL 技術棧的好處。你能夠把它當作是「現代 web 生態系統的 Rails」,讓你能夠在短短几個小時內作出你的 CRUD(增刪查改)型 app。(例如 Instagram clone

Gatsby

Gatsby 是一個 React 靜態網站生成器,它如今是基於 GraphQL 1.0 版本 開發。它一眼看上去像個奇怪的大雜膾,但其實它的功能十分強大。Gatsby 在構建過程當中,能夠從多個 GraphQL API 取得數據,而後用它們建立出一個全靜態的無後端 React app。

其它的 GraphQL 工具

GraphiQL

GraphiQL 是一個很是好用的基於瀏覽器的 IDE,它能夠方便你進行 GraphQL 端點查詢。

GraphiQL

DataLoader

因爲 GraphQL 的查詢一般是嵌套的,一個查詢可能會調用不少個數據庫請求。爲了不影響性能,你可使用一些批量出入庫框架和緩存庫,例如 Facebook 開發的 DataLoader。

Create GraphQL Server

Create GraphQL Server 是一個簡單的命令行工具,它能快速地幫你搭建好基於 Node 服務端與 Mongo 數據庫的 GraphQL 服務端。

GraphQL 服務

最後,這兒列了一些 GraphQL BAAS(後臺即服務)公司,它們已經爲你準備好了服務端的全部東西。這多是一個讓你嘗試一下 GraphQL 生態系統的很好的方式。

GraphCool

一個由 GraphQL 和 AWS Lambda 組成的一個彈性後端平臺服務,它提供了開發者免費計劃。

Scaphold

另外一個 GraphQL BAAS 平臺,它也提供了免費計劃。與 GraphCool 相比,它提供了更多的功能。(例如定製用戶角色、常規操做的回調鉤子等)

下面是一些能讓你學習 GraphQL 的資源。

GraphQL.org

GraphQL 的官方網站,有許多很好的文檔供你學習。

LearnGraphQL

LearnGraphQL 是由 Kadira 員工共同製做的課程。

LearnApollo

LearnApollo 是由 GraphCool 製做的免費課程,是對於 LearnGraphQL 課程的一個很好的補充。

Apollo 博客

Apollo 的博客有成噸的乾貨,有不少關於 Apollo 和 GraphQL 的超棒的文章。

GraphQL 週報

由 Graphcool 團隊策劃的一個簡報,其內容包括任何有關 GraphQL 的信息。

Hashbang 週報

另外一個不錯的簡報,除了 GraphQL 的內容外,還涵蓋了 React、Meteor。

Awesome GraphQL

一個關於 GraphQL 的連接和資源的很全面的清單。

你如何實踐你剛學到的 GraphQL 的知識呢?你能夠嘗試下面這些方式:

Apollo + Graphcool + Next.js

若是你對 Next.js 與 React 很熟悉,這個例子將會幫助你使用 Graphcool 很快的搭建好你的 GraphQL 端點,並在客戶端使用 Apollo 進行查詢。

VulcanJS

Vulcan 教程將會引導你建立一個簡單的 GraphQL 數據層,既有服務端部分也有客戶端部分。由於 Vulcan 是一個一站式平臺,因此這種無需任何配置的方式是一種很好的上手途徑。若是你須要幫助,請訪問咱們的 Slack 欄目

GraphQL & React 教程

Chroma 博客有一篇《分爲六部的教程》,講述瞭如何按照組件驅動的開發方式來構建一個 React/GraphQL app。

總結

當你剛開始接觸 GraphQL 可能會以爲它很是複雜,由於它橫跨了現代軟件開發的衆多領域。可是,若是你稍微花點時間去明白它的原理,我認爲你能夠找到它不少的可取之處。

因此無論你最後會不會用上它,我相信多瞭解瞭解 GraphQL 是值得的。愈來愈多的公司與框架開始接受它,過幾年它可能會成爲 web 開發的又一個重要組成部分。

贊同?不贊同?有疑問?請留下評論讓咱們知道你的見解。若是你還比較喜歡這篇文章,請點亮💚或者分享給他人。


掘金翻譯計劃 是一個翻譯優質互聯網技術文章的社區,文章來源爲 掘金 上的英文分享文章。內容覆蓋 AndroidiOSReact前端後端產品設計 等領域,想要查看更多優質譯文請持續關注 掘金翻譯計劃

相關文章
相關標籤/搜索