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

serverless教程
在这个例子中,数据层选择的是DynamoDB,但AppSync的数据源是AWS_LAMBDA(除此之外,还能选择AMAZON_DYNAMODB, AMAZON_ELASTICSEARCH, or AMAZON_OPENSEARCH_SERVICE)。也就是说,所有针对DynamoDB的CRUD操作都是通过相应Lambda实现的。
创建项目及设置
创建项目
首先创建一个项目并初始化:
bash
mkdir sls-appsync-graphql-demo
cd sls-appsync-graphql-demo
serverless create --template aws-nodejs添加依赖库
bash
yarn add serverless-appsync-pluginserverless.yml
在这里需要定义如下信息:
- DynamoDB相关信息
- AppSync基本信息:resolver到具体Lambda函数的映射
- Lambda函数
其源码:
yaml
service: sls-appsync-graphql-demo
frameworkVersion: '3'
provider:
name: aws
runtime: nodejs14.x
stage: dev
region: eu-west-1
iam:
role:
statements:
- Effect: "Allow"
Action:
- "dynamodb:PutItem"
- "dynamodb:UpdateItem"
- "dynamodb:DeleteItem"
- "dynamodb:GetItem"
- "dynamodb:Scan"
Resource: "arn:aws:dynamodb:${self:provider.region}:*:table/${self:custom.STUDENT_TABLE_NAME}"
custom:
STUDENT_TABLE_NAME: appsync-student-table
appSync:
name: appsync-student-demo
authenticationType: API_KEY
mappingTemplates:
- type: Mutation
field: createStudent
dataSource: createStudentFunction
request: false
response: false
- type: Mutation
field: updateStudent
dataSource: updateStudentFunction
request: false
response: false
- type: Mutation
field: deleteStudent
dataSource: deleteStudentFunction
request: false
response: false
- type: Query
field: getStudents
dataSource: getStudentsFunction
request: false
response: false
dataSources:
- type: AWS_LAMBDA
name: createStudentFunction
config:
functionName: createStudent
- type: AWS_LAMBDA
name: updateStudentFunction
config:
functionName: updateStudent
- type: AWS_LAMBDA
name: deleteStudentFunction
config:
functionName: deleteStudent
- type: AWS_LAMBDA
name: getStudentsFunction
config:
functionName: getStudents
functions:
getStudents:
handler: functions/getStudents.handler
environment:
STUDENT_TABLE_NAME: !Ref StudentTable
createStudent:
handler: functions/createStudent.handler
environment:
STUDENT_TABLE_NAME: !Ref StudentTable
updateStudent:
handler: functions/updateStudent.handler
environment:
STUDENT_TABLE_NAME: !Ref StudentTable
deleteStudent:
handler: functions/deleteStudent.handler
environment:
STUDENT_TABLE_NAME: !Ref StudentTable
resources:
Resources:
StudentTable:
Type: "AWS::DynamoDB::Table"
Properties:
KeySchema:
- AttributeName: id
KeyType: HASH
AttributeDefinitions:
- AttributeName: id
AttributeType: S
BillingMode: PAY_PER_REQUEST
TableName: ${self:custom.STUDENT_TABLE_NAME}
plugins:
- serverless-appsync-pluginGraphQL schema
增加文件schema.graphql:
GraphQL
schema {
query: Query
mutation: Mutation
}
type Query {
getStudents: [Get!]!
}
type Mutation {
createStudent(id: ID!, name: String!, address: String!): Save
updateStudent(id: ID!, name: String!, address: String!): Update
deleteStudent(id: ID!): Delete
}
type Get {
id: ID!
name: String
address: String
}
type Save {
id: ID!
name: String
address: String
}
type Update {
id: ID!
name: String
address: String
}
type Delete {
id: ID!
}GraphQL resolvers
functions/createStudent.js
JavaScript
const AWS = require("aws-sdk");
const dynamodb = new AWS.DynamoDB();
module.exports.handler = async (event) => {
const id = event.arguments.id;
const name = event.arguments.name;
const address = event.arguments.address;
const params = {
Item: {
id: {
S: id,
},
name: {
S: name,
},
address: {
S: address,
},
},
ReturnConsumedCapacity: "TOTAL",
TableName: process.env.STUDENT_TABLE_NAME,
};
return dynamodb
.putItem(params)
.promise()
.then((data) => {
return {
id,
name,
address,
};
})
.catch((err) => {
console.log(err);
});
};functions/deleteStudent.js
JavaScript
const AWS = require("aws-sdk");
const dynamodb = new AWS.DynamoDB();
module.exports.handler = async (event) => {
const id = event.arguments.id;
const params = {
Key: {
id: {
S: id,
},
},
TableName: process.env.STUDENT_TABLE_NAME,
};
return dynamodb
.deleteItem(params)
.promise()
.then((data) => {
return {
id,
};
})
.catch((err) => {
console.log(err);
});
};functions/getStudents.js
JavaScript
const AWS = require("aws-sdk");
const dynamodb = new AWS.DynamoDB();
module.exports.handler = async (event) => {
const params = {
TableName: process.env.STUDENT_TABLE_NAME,
};
return dynamodb
.scan(params)
.promise()
.then((data) => {
const studentList = [];
for (let i = 0; i < data.Items.length; i++) {
studentList.push({
id: data.Items[i].id.S,
name: data.Items[i].name.S,
address: data.Items[i].address.S,
});
}
return studentList;
})
.catch((err) => {
console.log(err);
});
};functions/updateStuent.js
JavaScript
const AWS = require("aws-sdk");
const dynamodb = new AWS.DynamoDB();
module.exports.handler = async (event) => {
const id = event.arguments.id;
const name = event.arguments.name;
const address = event.arguments.address;
const params = {
ExpressionAttributeNames: {
"#n": "name",
"#d": "address",
},
ExpressionAttributeValues: {
":n": {
S: name,
},
":d": {
S: address,
},
},
Key: {
id: {
S: id,
},
},
ReturnValues: "ALL_NEW",
TableName: process.env.STUDENT_TABLE_NAME,
UpdateExpression: "SET #n = :n, #d = :d",
};
return dynamodb
.updateItem(params)
.promise()
.then((data) => {
const body = data.Attributes;
return {
id: body.id.S,
name: body.name.S,
address: body.address.S,
};
})
.catch((err) => {
console.log(err);
});
};部署及测试
运行如下命令部署:
bash
sls deploy进入AWS AppSync控制台,就可以进行测试了:

AWS AppSync
最后不要忘记删除这个APP对应的资源:
bash
sls remove