我經常聽到的 GraphQL 到底是什麼

我經常聽到的 GraphQL 到底是什麼?

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

1. 嫌棄

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

2. 感興趣

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

3. 恐慌

救命啊!我必須馬上去學這個新庫,否則我就會被淘汰了!

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

因此,現在就是學習 GraphQL 這個你常常聽到別人談論的東西的最好時機!

基礎

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

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

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

<figure>

image

<figcaption></figcaption>

</figure>

遇到的問題

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

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

<figure>

image

<figcaption></figcaption>

</figure>

但是現在你是在開發移動 app,加載所有的數據明顯會降低 app 的速度。所以你得請求兩個接口(API),一個包含了 likes 的信息,另一個不含這些信息(只含有文章信息)。

現在我們再摻入另一種情況:posts 數據是由 MySQL 數據庫存儲的,而 likes 數據卻是由 Redis 存儲的。現在你該怎麼辦?

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

解決的方案

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

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

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

<figure>

image

<figcaption></figcaption>

</figure>

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

<figure>

image

<figcaption></figcaption>

</figure>

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

<figure>

image

<figcaption></figcaption>

</figure>

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

<figure>

image

<figcaption></figcaption>

</figure>

理論上,一個 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
  }
}

<figure>

image

<figcaption></figcaption>

</figure>

GraphQL 的自動補全功能

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

<figure>

image

<figcaption></figcaption>

</figure>

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 官方文檔

<figure>

image

<figcaption></figcaption>

</figure>

常見問題

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

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

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 客戶端 來連接你的節點。

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

<figure>

image

<figcaption></figcaption>

</figure>

現在你應該對 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 本身是一個有着豐富生態系統的超棒的狀態管理類庫。

<figure>

image

<figcaption></figcaption>

</figure>

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

開源 App

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

VulcanJS

 

<figure>[

image

<figcaption></figcaption>](https://link.juejin.im?target=http%3A%2F%2Fvulcanjs.org) </figure>

首先我得聲明一下,我是 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 端點查詢。

 

<figure>[

image

<figcaption></figcaption>](https://link.juejin.im?target=https%3A%2F%2Fgithub.com%2Fgraphql%2Fgraphiql) </figure>

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 相比,它提供了更多的功能。(例如定製用戶角色、常規操作的回調鉤子等)

<figure>

image

<figcaption></figcaption>

</figure>

下面是一些能讓你學習 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 的鏈接和資源的很全面的清單。

<figure>

image

<figcaption></figcaption>

</figure>

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

Apollo + Graphcool + Next.js

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

VulcanJS

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

GraphQL & React 教程

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

<figure>

image

<figcaption></figcaption>

</figure>

總結

當你剛開始接觸 GraphQL 可能會覺得它非常複雜,因爲它橫跨了現代軟件開發的衆多領域。但是,如果你稍微花點時間去明白它的原理,我認爲你可以找到它很多的可取之處。

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



作者:中v中
鏈接:https://www.jianshu.com/p/d601f43e018d
來源:簡書
著作權歸作者所有。商業轉載請聯繫作者獲得授權,非商業轉載請註明出處。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章