在开发无服务器应用的时候,通过纯手工方式创建各种资源的话,效率会非常低,因此需要借助一些框架来提高开发效率。下面介绍如何在serverless中开发GraphQL API(AWS + DynamoDB)。

serverless教程
注意:下面方式并没有使用AWS AppSync,而是创建一个普通的Lambda,在调用Lambda的时候会启动一个ApolloServer。
创建项目及设置
创建项目
首先创建一个项目并初始化:
bash
mkdir sls-graphql-demo
cd sls-graphql-demo
yarn init -y添加依赖库
bash
yarn add apollo-server-lambda graphql
yarn add -D serverless-offlineGraphQL相关定义
添加文件src/schema.graphql:
JavaScript
type Query {
item(id: ID!): Item
}
type Mutation {
createItem(content: String!): Item
}
type Item {
id: ID!
content: String
}添加文件src/graphql.js:
JavaScript
const fs = require('fs')
const { ApolloServer, gql } = require('apollo-server-lambda')
const schema = fs.readFileSync('./src/schema.graphql', 'utf8')
const resolvers = {
Query: {
item: () => {},
},
Mutation: {
createItem: () => {},
}
};
const server = new ApolloServer({ typeDefs: schema, resolvers })
// 当Lambda被调用时启动服务器
exports.handler = server.createHandler();serverless相关配置
添加文件:serverless.yml
yaml
service: sls-graphql-example
provider:
name: aws
runtime: nodejs14.x
region: eu-west-1
apiGateway:
shouldStartNameWithService: true
functions:
graphql:
handler: src/graphql.handler
events:
- http:
path: graphql
method: any # 所有类型的HTTP请求都会访问这个Lambda
cors: true
plugins:
- serverless-offline更新package.json
json
"scripts": {
"local": "sls offline"
}测试
运行如下命令启动服务:
bash
yarn local在界面中进行简单查询:
graphql
query DemoQuery {
item(id: "01") {
id
}
}由于目前还没有任何数据,自然不能返回任何值了:
json
{
"data": {
"item": null
}
}连接DyanmoDB
添加依赖库:
bash
yarn add uuid
yarn add -D aws-sdk定义serverless资源
首先更新serverless.yml:
yaml
service: sls-graphql-example
provider:
name: aws
runtime: nodejs14.x
region: eu-west-1
environment:
TABLE_NAME: sls-graphql-table
apiGateway:
shouldStartNameWithService: true
iam:
role:
statements:
- Effect: Allow
Action:
- dynamodb:GetItem
- dynamodb:PutItem
Resource: 'arn:aws:dynamodb:${self:provider:region, self:provider.region}:*:table/${self:provider.environment.TABLE_NAME}'
functions:
graphql:
handler: src/graphql.handler
events:
- http:
path: graphql
method: any
cors: true
resources:
Resources:
ItemsTable:
Type: 'AWS::DynamoDB::Table'
Properties:
AttributeDefinitions:
- AttributeName: itemId
AttributeType: S
KeySchema:
- AttributeName: itemId
KeyType: HASH
ProvisionedThroughput:
ReadCapacityUnits: 1
WriteCapacityUnits: 1
TableName: ${self:provider.environment.TABLE_NAME}
plugins:
- serverless-offline更新GraphQL相关文件
安装新的依赖库:
none
yarn add uuid更新graphql.js
JavaScript
const fs = require('fs')
const { ApolloServer, gql } = require('apollo-server-lambda')
const AWS = require('aws-sdk')
const { v4: uuidv4 } = require('uuid')
const schema = fs.readFileSync('./src/schema.graphql', 'utf8')
const resolvers = {
Query: {
item: async (_, { id }) => {
const dynamoDb = new AWS.DynamoDB.DocumentClient()
const params = {
TableName: process.env.TABLE_NAME,
Key: {
itemId: id,
},
}
const { Item } = await dynamoDb.get(params).promise()
return {
...Item,
id: Item.itemId,
}
},
},
Mutation: {
createItem: async (_, { content }) => {
const dynamoDb = new AWS.DynamoDB.DocumentClient()
const id = uuidv4()
const params = {
TableName: process.env.TABLE_NAME,
Item: {
itemId: id,
content,
},
}
await dynamoDb.put(params).promise()
return {
content,
id,
}
},
}
};
const server = new ApolloServer({ typeDefs: schema, resolvers })
exports.handler = server.createHandler();测试
部署到AWS后,对应的URL类似于:https://xxxxxxxxx.execute-api.eu-west-1.amazonaws.com/dev/graphql
query
进行如下查询:
graphql
query Query {
item(id: "01") {
id
content
}
}mutation
使用如下的GraphQL进行测试:
graphql
mutation CreateItem($content: String!) {
createItem(content: $content) {
content
}
}配套参数:
json
{
"content": "test content"
}其返回值为:
json
{
"data": {
"createItem": {
"content": "test content"
}
}
}