This is a Serverless project example using Typescript, ready for AWS Lambda and API Gateway.
You need to have an AWS account, to create a dedicated IAM User with credentials so Serverless can deploy your app. (Configure AWS credentials)
- Node.js 12x
- Serverless
- Typescript (> 3.8) for type checking.
- A sample docker-compose.yml, which allow us to test our App with Docker.
VSCode is highly preferred. Please ensure you have installed these extensions:
- Prettier
- Eslint
You can clone this repo and use it with docker, or jump to the next section and follow the instructions to set up your application step by step
# host project dir
cd serverless-typescript-aws
# Up container
docker-compose up -d
# Attach to node container
docker exec -ti node sh
# container project dir
cd /var/www/serverless-typescript-aws
# install dependencies
npm install
- Node.js
Use our node container (set up in docker-compose.yml
)
Or install Node 12 : https://nodejs.org/en/
- Serverless
npm install -g serverless
Let's start to initialize our project with the Serverless template "aws-nodejs-typescript"
serverless create --template aws-nodejs-typescript
Now we have initial handler.ts, serverless.yml, tsconfig.json and webpack.config.js files.
npm install --save-dev eslint @typescript-eslint/parser @typescript-eslint/eslint-plugin
- Create
.eslintrc.js
module.exports = {
extends: [
'eslint:recommended',
'plugin:@typescript-eslint/eslint-recommended',
'plugin:@typescript-eslint/recommended',
],
env: {
node: true,
},
parser: '@typescript-eslint/parser',
plugins: ['@typescript-eslint'],
settings: {
'import/parsers': {
'@typescript-eslint/parser': ['.ts', '.tsx'],
},
'import/resolver': {
typescript: {},
},
},
parserOptions: {
project: './tsconfig.json',
tsconfigRootDir: './',
sourceType: 'module',
ecmaVersion: 2019,
},
rules: {
'@typescript-eslint/no-explicit-any': 'off',
},
};
- Create
.eslintignore
:
node_modules
.serverless
.vscode
*.config.js
.webpack
**/*.js
npm install --save-dev prettier eslint-config-prettier eslint-plugin-prettier
- Create
.prettierrc.js
module.exports = {
printWidth: 120,
singleQuote: true,
trailingComma: 'all',
};
- Create
.prettierignore
node_modules
.serverless
.webpack
- Update
.eslintrc.js
rules
extends: [
"prettier/@typescript-eslint", // Uses eslint-config-prettier to disable ESLint rules from @typescript-eslint/eslint-plugin that would conflict with prettier
"plugin:prettier/recommended" // Enables eslint-plugin-prettier and eslint-config-prettier. This will display prettier errors as ESLint errors. Make sure this is always the last configuration in the extends array.
],
Enable Webpack plugin that runs TypeScript type checker on a separate process.
Update webpack.config.js
plugins: [
new ForkTsCheckerWebpackPlugin({
eslint: true,
eslintOptions: {
cache: true,
},
}),
],
// handler.ts
import { APIGatewayProxyHandler, APIGatewayEvent, Context, Callback } from 'aws-lambda';
import 'source-map-support/register';
export const hello: APIGatewayProxyHandler = async (
event: APIGatewayEvent,
context: Context,
callback: Callback,
): Promise<any> => {
return {
statusCode: 200,
body: JSON.stringify(
{
message: 'Go Serverless Webpack (Typescript) v1.0! Your function executed successfully!',
input: event,
context: context,
callback: callback,
},
null,
2,
),
};
};
Let's add some scripts for our application in package.json
"scripts": {
"lint": "eslint . --ext js,ts --cache --fix",
"prettier": "prettier --list-different './**/*.{js,ts}'",
"typecheck": "tsc --noEmit",
"test": "echo \"Error: no test specified\" && exit 1"
},
Test them :
# linter
npm run lint
# prettier
npm run prettier
# type checking
npm run typecheck
This is the quick way to set up a user for Serverless.
Here is a better way : Configure AWS Credentials (Better way)
- Login to AWS and navigate to IAM
- Create a new user called serverless-deploy
- Give serverless-deploy Programatic access
- Attach the AdministratorAccess policy
Save your new AWS profile into ~/.aws/credentials
(Don't forget to set your values :D) :
[serverless-deploy]
aws_access_key_id = XXX
aws_secret_access_key = XXX
region = XXX
Set this profile in your serverless.yml
so Serverless can use it for deployment.
provider:
profile: serverless-deploy
(or pass it with --profile
argument to serverless deploy
command.)
Here is our final serverless.yml
:
service:
name: serverless-typescript-aws
custom:
webpack:
webpackConfig: ./webpack.config.js
includeModules: true
# Add the serverless-webpack plugin
plugins:
- serverless-webpack
provider:
name: aws
runtime: nodejs12.x
profile: serverless-deploy
apiGateway:
minimumCompressionSize: 1024 # Enable gzip compression for responses > 1 KB
environment:
AWS_NODEJS_CONNECTION_REUSE_ENABLED: 1 # reuse HTTP connections : https://docs.aws.amazon.com/sdk-for-javascript/v2/developer-guide/node-reusing-connections.html
functions:
hello:
handler: handler.hello
events:
- http:
method: get
path: hello
# -v enables verbose output so you can see what happens
serverless deploy -v
Dev stage is assumed by default.
What do Serverless do ?
- Package our application (with Webpack)
- Creates a CloudFormation stack
- Create a S3 Bucket
- Upload the CloudFormation template to S3
- Upload our application package to S3
- Provisions the IAM Roles
- Provisions the Log Groups
- Provisions the ApiGateway end points
- Provisions the Lambda function our service
You can now invoke your service :
# -f specifies the function name, -l specifiesto output the logs to the console
serverless invoke -f hello -l
You can test it with your API Gateway end point : https://xxxxxx.execute-api.us-east-1.amazonaws.com/dev
serverless remove
Here we want to create a new IAM Policy, attach it to a new IAM group to which we will attach our new user.
Let's go to Identity and Access Management (IAM) service and create a new User serverless-deploy
with Programatic access.
Give it no permissions.
You can find how to use your user credentials with Serverless here : Use your user credentials
Then try to deploy your serverless app
serverless deploy -v
You should get this error...
serverless-deploy is not authorized to perform: cloudformation:DescribeStacks
It's enough explicit :)
So we now need to give this IAM User permission.
//
Let's go back to AWS Console, and create a new IAM Group serverless-deploy-group
without any policy.
Let's now create a new IAM Policy :
- Create a new IAM Policy
- Add a policy for the CloudFormation service, allow List:DescribeStacks action.
- Indicate to apply this permission to all resources and click Review Policy button.
(If necessary, you can specify specific ressources to apply the permissions) - Name this policy
serverless-deploy-policy
(just for consistency) and finish to create it.
Now go back to the group serverless-deploy-group
we created and attach it this policy.
Then go back to the user serverless-deploy
and attach it to the group serverless-deploy-group
.
Let's now try to deploy again
serverless deploy -v
Now you should have the following new error.
serverless-deploy is not authorized to perform: cloudformation:CreateStack on resource
We have to edit our policy and add some new permissions.
//
Go back to the serverless-deploy-policy
policy we created, edit it and add the CreateStack permission for CloudFormation service.
You can try to deploy again, and add each missing policy.
This is the best way to be sure to add only the necessary permissions.
Step by step, it will sometimes be necessary to delete resources manually to be able to test a deployment again.
For this example project, you can find the minimum permissions required here : IAM.json
WIP :)
Now it's your time !
Update your function, update your provider config, create new functions, and deploy your service(s) as you want :D