這是一個關於如何使用Node.js和Express創建GraphQL服務器的簡單教程。
首先,創建一個新的Node.js項目,如果您還沒有設置一個的話:
npm init --y
這個命令會創建我們使用npm所需的package.json
文件。
安裝npm包express
,graphql
和express-graphql
:
npm install express graphql express-graphql
創建一個app.js
文件,並開始初始化Express服務器:
const express = require('express')
const app = express()
app.listen(3000, () => {
console.log('App listening on port 3000')
})
現在我們添加express-graphql
庫,它是一個中間件(middleware),我們將它應用於/graphql
路由:
const express = require('express')
const graphqlHTTP = require('express-graphql')
const app = express()
app.use('/graphql', graphqlHTTP())
app.listen(3000, () => {
console.log('App listening on port 3000')
})
我們需要傳遞一個對象,該對象包含了 schema
屬性,該屬性必須包含一個schema定義。
我們首先需要定義一個schema!
創建一個schema.js
文件,然後在其中引入graphql
庫,使用對象解構語法,我們獲取GraphQLSchema
,GraphQLObjectType
和GraphQLString
這幾個對象:
const graphql = require('graphql')
const { GraphQLSchema, GraphQLObjectType, GraphQLString } = graphql
然後,我們通過初始化一個新的GraphQLSchema
實例,並傳遞一個對象給它,該對象包含一個query
屬性。該屬性是一個GraphQLObjectType
對象的實例:
const schema = new GraphQLSchema({
query: new GraphQLObjectType({
//...
}),
})
module.exports = schema
在這個新對象中,我們必須指定一個name
和一個fields
屬性。這個fields
屬性是一個對象,其中包含我們的schema的每個字段的屬性。在這個例子中,我們設置了一個hello
字段:
const schema = new GraphQLSchema({
query: new GraphQLObjectType({
name: 'RootQueryType',
fields: {
hello: {
type: GraphQLString,
resolve() {
return 'world'
},
},
},
}),
})
resolve()
方法返回字符串world
,這意味著當我們請求hello
字段時,我們將得到這個字符串。
以下是完整的schema.js
文件內容:
const graphql = require('graphql')
const { GraphQLSchema, GraphQLObjectType, GraphQLString } = graphql
const schema = new GraphQLSchema({
query: new GraphQLObjectType({
name: 'RootQueryType',
fields: {
hello: {
type: GraphQLString,
resolve() {
return 'world'
},
},
},
}),
})
module.exports = schema
現在,讓我們回到我們的app.js
文件。
這是我們有的:
const express = require('express')
const graphqlHTTP = require('express-graphql')
const app = express()
app.use('/graphql', graphqlHTTP())
app.listen(3000, () => {
console.log('App listening on port 3000')
})
現在我們需要引入schema.js
文件:
const schema = require('./schema.js')
並將其添加到我們傳遞給graphqlHTTP()
構造函數的對象中:
app.use(
'/graphql',
graphqlHTTP({
schema: schema,
})
)
好的!
我們現在可以測試一下,看看它是否正常工作。我們可以使用GraphiQL,這是一個很好的測試GraphQL API的工具。
它已經安裝好了,要啟用它,我們需要給graphqlHTTP
構造函數傳遞另一個屬性:
app.use(
'/graphql',
graphqlHTTP({
schema: schema,
graphiql: true,
})
)
現在你運行node app.js
,在瀏覽器中訪問http://localhost:3000/graphql
URL,你將看到GraphiQL的頁面:
你可以測試第一個API調用,傳遞這個查詢:
{
hello
}
這是返回結果:
現在讓我們來構建一個更複雜的schema。
一個具有嵌套類型的schema。
我腦中有一個例子是一個博客文章。
一篇博客文章有標題、描述,還有作者。作者有一個名字。
讓我們來想一下。
首先,我們添加一組文章和作者:
const posts = [
{
title: 'First post',
description: 'Content of the first post',
author: 'Flavio',
},
{
title: 'Second post',
description: 'Content of the second post',
author: 'Roger',
},
]
const authors = {
Flavio: {
name: 'Flavio',
age: 36,
},
Roger: {
name: 'Roger',
age: 7,
},
}
這就是我們將從哪獲取數據。
接下來,我們定義了3個GraphQLObjectType
實例:
authorType
,定義了作者的數據postType
,定義了文章的數據queryType
,主要一個
我們先從作者開始。一個作者有名字和年齡。
我們使用了GraphQLInt
類型,我們需要先引入它:
const { GraphQLSchema, GraphQLObjectType, GraphQLString, GraphQLInt } = graphql
//...
const authorType = new GraphQLObjectType({
name: 'Author',
fields: {
name: {
type: GraphQLString,
},
age: {
type: GraphQLInt,
},
},
})
接下來是postType
。一篇文章有標題和描述(都是字符串),還有一個作者。一個作者是authorType
類型,我們剛剛定義了這個類型,並且它有一個解析器。
我們從source
參數中獲取作者的名字,source
參數是傳遞給文章對象的參數,然後根據它查找作者數據。我們將其返回。
const postType = new GraphQLObjectType({
name: 'Post',
fields: {
title: {
type: GraphQLString,
},
description: {
type: GraphQLString,
},
author: {
type: authorType,
resolve: (source, params) => {
return authors[source.author]
},
},
},
})
注意,解析器函數可以是異步的,所以你可以使用async/await從數據庫或者網絡中查詢資源。
接下來是queryType,這是我們將添加到schema中的根類型。在其中,我們定義了2個字段:
post
一篇博客文章,根據id來識別posts
文章列表
它們都有一個解析器函數來查找在posts
數組中的數據:
const queryType = new GraphQLObjectType({
name: 'Query',
fields: {
post: {
type: postType,
args: {
id: { type: GraphQLInt },
},
resolve: (source, { id }) => {
return posts[id]
},
},
posts: {
type: new GraphQLList(postType),
resolve: () => {
return posts
},
},
},
})
注意到了新的GraphQLList
類型,我們使用它來將postType
包裹起來,表示它是一個postType
對象的列表。我們必須在頂部引入它:
const {
GraphQLSchema,
GraphQLObjectType,
GraphQLString,
GraphQLList,
GraphQLInt,
} = graphql
這樣就完成了。我們需要將它添加到我們的schema
中,我們就完成了:
const schema = new GraphQLSchema({
query: queryType,
})
這是完整的代碼:
const graphql = require('graphql')
const {
GraphQLSchema,
GraphQLObjectType,
GraphQLString,
GraphQLList,
GraphQLInt,
} = graphql
const posts = [
{
title: 'First post',
description: 'Content of the first post',
author: 'Flavio',
},
{
title: 'Second post',
description: 'Content of the second post',
author: 'Roger',
},
]
const authors = {
Flavio: {
name: 'Flavio',
age: 36,
},
Roger: {
name: 'Roger',
age: 7,
},
}
const authorType = new GraphQLObjectType({
name: 'Author',
fields: {
name: {
type: GraphQLString,
},
age: {
type: GraphQLInt,
},
},
})
const postType = new GraphQLObjectType({
name: 'Post',
fields: {
title: {
type: GraphQLString,
},
description: {
type: GraphQLString,
},
author: {
type: authorType,
resolve: (source, params) => {
return authors[source.author]
},
},
},
})
const queryType = new GraphQLObjectType({
name: 'Query',
fields: {
post: {
type: postType,
args: {
id: { type: GraphQLInt },
},
resolve: (source, { id }) => {
return posts[id]
},
},
posts: {
type: new GraphQLList(postType),
resolve: () => {
return posts
},
},
},
})
const schema = new GraphQLSchema({
query: queryType,
})
module.exports = schema