GraphQL 是什么
GraphQL is a query language created by Facebook in 2012 which provides a common interface between the client and the server for data fetching and manipulations.
The client asks for various data from the GraphQL server via queries. The response format is described in the query and defined by the client instead of the server: they are called client‐specified queries. The structure of the data is not hardcoded as in traditional REST APIs - this makes retrieving data from the server more efficient for the client.
GraphQL 是 Facebook 開(kāi)發(fā)的一個(gè)應(yīng)用層的數(shù)據(jù)查詢語(yǔ)言颅筋。通過(guò) GraphQL慨亲,客戶端可以從服務(wù)端的數(shù)據(jù)集中輕松獲得一個(gè)自定義結(jié)構(gòu)的數(shù)據(jù)。
假設(shè)某個(gè)業(yè)務(wù)需要以下數(shù)據(jù)內(nèi)容 a:
{
user(id: 3500401) {
id,
name,
isViewerFriend
}
}
沒(méi)錯(cuò)晋渺,這不是 json,但我們?nèi)匀豢梢钥炊硎镜氖遣樵?id
為 3500401 用戶的 id
,name
和 isViewerFriend
信息稍刀。
用戶信息對(duì)于各個(gè)業(yè)務(wù)都是通用的,假設(shè)另外一個(gè)業(yè)務(wù)需要這樣的用戶信息 b:
{
user(id: 3500401) {
name,
profilePicture(size: 50) {
uri,
width,
height
}
}
}
一般來(lái)說(shuō)敞曹,用戶信息對(duì)應(yīng)的數(shù)據(jù)模型都是固定的,每次請(qǐng)求其實(shí)就是對(duì)數(shù)據(jù)做過(guò)濾和篩選综膀。對(duì)應(yīng)到數(shù)據(jù)庫(kù)操作澳迫,就是數(shù)據(jù)的查詢操作。如果客戶端也能夠發(fā)送“查詢”請(qǐng)求剧劝,那不就可以從后端接口這個(gè)大的“數(shù)據(jù)集”中去過(guò)濾篩選業(yè)務(wù)所需要的數(shù)據(jù)了嗎橄登?
GraphQL 就是基于這樣的思想來(lái)設(shè)計(jì)的。上面提到的(a)和(b)類(lèi)型的數(shù)據(jù)結(jié)構(gòu)就是 GraphQL 的查詢內(nèi)容讥此。使用上面的查詢拢锹,GraphQL 服務(wù)器會(huì)分別返回如下響應(yīng)內(nèi)容。
a 查詢對(duì)應(yīng)的響應(yīng):
{
"user" : {
"id": 3500401,
"name": "Jing Chen",
"isViewerFriend": true
}
}
b 查詢對(duì)應(yīng)的響應(yīng):
{
"user" : {
"name": "Jing Chen",
"profilePicture": {
"uri": "http: //someurl.cdn/pic.jpg",
"width": 50,
"height": 50
}
}
}
只需要改變查詢內(nèi)容萄喳,前端就能定制服務(wù)器返回的響應(yīng)內(nèi)容卒稳,這就是 GraphQL 的客戶端指定查詢(Client Specified Queries)。
實(shí)現(xiàn) GraphQL 服務(wù)器
第一步:
- 創(chuàng)建工程目錄
hello-graphql
- 初始化項(xiàng)目他巨,以及引入所需的包
npm init -f
npm install graphql express express-graphql --save
npm install babel-cli babel-preset-es2015 --save-dev
npm install -g nodemon
第二步:
在項(xiàng)目根目錄下創(chuàng)建 data 目錄充坑,并在該目錄下創(chuàng)建 data.json
文件减江,并輸入以下內(nèi)容:
{
"1": {
"id": "1",
"name": "Dan"
},
"2": {
"id": "2",
"name": "Marie"
},
"3": {
"id": "3",
"name": "Jessie"
}
}
第三步:
創(chuàng)建 server.js
文件,并輸入以下內(nèi)容:
import express from 'express'
const app = express()
const port = 3000
app.get('/', (req, res) => {
res.send('Hello!');
});
let server = app.listen(port, function () {
let addr = server.address();
let bind = typeof addr === 'string' ? 'pipe ' + addr : 'port ' + addr.port;
console.log('Listening on ' + bind);
});
命令行運(yùn)行:nodemon --exec babel-node --presets=es2015 server.js
捻爷,瀏覽器輸入:http://localhost:3000 辈灼。顯示 Hello!,說(shuō)明你的 express 服務(wù)已經(jīng) OK 了也榄。
第四步:
創(chuàng)建文件夾 /src/schema巡莹,并創(chuàng)建文件 index.js
。并在 index.js
文件中編寫(xiě)GraphQL Schema甜紫。Schema 是 GraphQL 請(qǐng)求的入口榕莺,用戶請(qǐng)求的
GraphQL 將會(huì)對(duì)應(yīng)到具體的 Schema。
import {
GraphQLObjectType,
GraphQLSchema,
GraphQLString,
GraphQLInt
} from 'graphql'
// 我們要用的模擬數(shù)據(jù)
const data = require('../../data/data.json')
const User = new GraphQLObjectType({
name: 'User',
description: 'User對(duì)象',
fields: {
id: {
type: GraphQLInt
},
name: {
type: GraphQLString
},
}
});
const Query = new GraphQLObjectType({
name: 'Query',
fields: {
user: {
type: User,
args: {
id: {
type: GraphQLInt
}
},
resolve: function (_, args) {
return data[args.id];
}
}
}
});
const Schema = new GraphQLSchema({
query: Query
});
export default Schema;
第五步:
修改 server.js
文件棵介,連接 schema钉鸯。將 server.js
文件修改為以下內(nèi)容:
import express from 'express'
import Schema from './src/schema'
import graphqlHTTP from 'express-graphql'
const app = express()
const port = 3000
app.use('/', graphqlHTTP({
schema: Schema,
graphiql: true
}));
let server = app.listen(port, function () {
var addr = server.address();
var bind = typeof addr === 'string' ? 'pipe ' + addr : 'port ' + addr.port;
console.log('Listening on ' + bind);
});
這時(shí),在瀏覽器中可以查看到如下界面:
在左邊的空白處輸入:
{
user(id: 1) {
name
}
}
點(diǎn)擊“運(yùn)行”按鈕邮辽,右邊會(huì)出現(xiàn)結(jié)果:
{
"data": {
"user": {
"name": "Dan"
}
}
}
總結(jié)
至此唠雕,我們已經(jīng)搭建好了簡(jiǎn)單的 GraphQL 服務(wù)器。