GraphQL是一種面向數據的API查詢風格。javascript
GraphQL是由Facebook主導開發的一款面向數據的API查詢語言。客戶端只需給他一個描述,而後GraphQL就能從數據庫組合出符合描述的數據並返回。前端
在開發中咱們通常都使用的是RESTful API,它是是面向資源的。一般渲染一個頁面咱們須要多個資源,REST API請求多個資源時就會載入多個URL,而GraphQL能夠經過一次請求就能夠獲取到須要的全部數據。java
解決痛點:數據庫
接口返回數據格式並非調用者(前端)理想型npm
多個資源只用一個請求,減小服務器壓力json
數據字段由調用者控制後端
GraphQL 既是一種用於 API 的查詢語言也是一個知足你數據查詢的運行時。 GraphQL 對你的 API 中的數據提供了一套易於理解的完整描述,使得客戶端可以準確地得到它須要的數據,並且沒有任何冗餘,也讓 API 更容易地隨着時間推移而演進,還能用於構建強大的開發者工具。數組
示例:瀏覽器
這裏以掘金的首頁舉例,它可能分爲這幾個資源(文章列表,分類列表,做者榜)bash
REST API
文章列表/articles
[
{
title: 'xxx',
content: 'xxx內容'
}
]
複製代碼
分類列表/categories
[
{
id: '1'
name: '前端',
},
{
id: '2'
name: '後端',
},
]
複製代碼
做者推薦榜/recommendationAuthor
[
{
id: 1,
username: '張三'
}
]
複製代碼
上面是用REST接口來獲取首頁須要的數據,須要發送3次請求,再看下GraphQL的請求是什麼樣?
GraphQL查詢接口/graphql/query
query getHomePage() {
articleList($first: 0) {
title
content
},
categoryList(){
id
name
},
recommendationAuthorList($limit: 10) {
id
username
},
}
複製代碼
經過Graphql只用請求一次就能夠拿到所有信息,返回的數據格式都是由調用者控制的,很少很多。
這裏先介紹幾個GraphQL比較重要的概念,能夠參考着GraphQL官網文檔看。
操做類型能夠是query、mutation、substription ,描述你打算作什麼類型的操做。
每個Graphql都有一個query
類型,也可能有一個mutation
類型。他們定義了每個Graphql查詢的入口。
有符號32位整數
有符號雙精度浮點數
UTF-8字符序列
true或者false
ID標量類型標識一個惟一標識符
type Article{
title: String
author: [User]
}
複製代碼
上面我聲明瞭一個GraphQL對象類型,這裏聲明瞭兩個字段並指定了字段類型。
String是內置的標量類型之一,查詢中沒法對他進行次級選擇。
[User] 表示一個User數組,數組中的每一個項目都是一個User對象。
User對象怎麼來的呢?
如Article同樣 使用type
關鍵字聲明
type User {
name: String
age: Int
}
複製代碼
聲明對象有什麼用?
經過Query對外提供查詢入口時,咱們一般都是以一個對象爲一個單位。能夠把每一個對象看做成一個接口。
經過Mutation對外提供變動入口。有時你須要傳遞一整個對象做爲新建對象,以前的標量類型就不能知足了。
官網示例:
客戶端使用前,咱們須要在服務端定義Schema結構。
PS: 下載太慢時能夠先全局安裝egg-init腳手架,再執行egg-init --type simple --registry china
使用淘寶鏡像生成項目
執行npm i egg-apollo-server --save
在egg項目中添加graphql的相關配置, 詳見egg-apollo-server
這裏我沒有用egg-graphql插件而使用的是egg-apollo-server
PS:config.graphql.subscriptions用來對grapql請求作鑑權的,在此demo裏不須要改成false便可
├── app
│ ├── controller
│ │ └── home.js
│ ├── graphql
│ │ ├── article
│ │ │ ├── resolver.js
│ │ │ └── schema.graphql
│ ├── router.js
│ └── service
├── config
│ ├── config.default.js
│ └── plugin.js
├── package.json
└── package-lock.json
複製代碼
schema.graphql
定義GraphQL類型和操做
extend type Query {
articleList(first: ID): [Article]
}
type Article {
id: ID
title: String
content: String
author: Author
}
type Author {
name: String
age: Int
}
extend type Mutation {
addArticle(title: String, content: String, author: AddAuthor): Article
}
input AddArticle {
title: String
content: String
}
input AddAuthor {
name: String
age: Int
}
複製代碼
resolver.js
實現操做
'use strict';
const list = [
{
id: 1,
content: 'aaa',
title: '',
author: {
name: 'aaa',
age: 18,
},
},
{
id: 2,
content: 'bbb',
title: '',
author: {
name: 'aaa',
age: 18,
},
},
];
module.exports = {
Query: {
articleList: () => {
return list;
},
},
Mutation: {
addArticle(root, params, ctx) {
console.log(params);
params.id = list.length++;
list.push(params);
return params;
},
},
};
複製代碼
瀏覽器打開 http://127.0.0.1:7001/graphql進行調試
PS: 測試前須要關閉csrf保護,不然調試發送的post請求將會被攔截
左側爲查詢區,在這裏寫操做語句。右側爲執行結果。
{
articleList(first: 0){
id
title
content
author{
name
age
}
}
}
複製代碼
mutation {
addArticle(title: "title", content: "content", author: {name: "張三", age: 15}){
title
content
id
}
}
複製代碼