Content:
What is Serverless Framework
Whether you use AWS, Google Cloud or Azure for your application infrastructure, maintaining all devops components through the interface can quickly become a fulltime job itself. Not to mention that when multiple developers work on the same project, they would all have to go to their console and manually apply changes done to the infrastructure by each developer.
This is where serverless framework comes into play. It is a tool that you can use to deploy or remove infrastructure components using a configuration file and the CLI. This is the so popular called infrastructure as code.
Let’s take an example with AWS.
Using a <filename>.yml configuration file you can define all lambdas that you would like to get deployed to your aws account automatically using just one CLI command. It uses CloudFormation behind the scenes to create stacks on your behalf.
It is a great tool but as with every tool, it has its limitations, especially with AWS. I am no expert in CloudFormation but this could be the reason why serverless framework is kind of limited in managing stateful infrastructure components such as Cognito Userpools, Cognito Identity Pools, dynamodb etc.
I totally recommend using it for managing your lambdas deployment.
Context
Serverless documentation is written using .js files in a typescript world. Having a complex application developed in vanilla javascript can become a pain to maintain and add up features. For this very reason a lot of developers started or planning to start their serverless application backend using js instead of typescript.
So the question is, how could you use serverless framework with Typescript ?
Their documentation isn’t that great and if you search on google, you get multiple suggestions & packages that you can use, every solution coming with its own issues and errors.
I’ll summarize and give you only one very simple solution.
Let’s get started.
Configuration
Let’s first take an example of configuration file. Let’s say you have a microservice / module called company which contains all the endpoints related to the company.
service: company
custom:
http: &http
cors: true
authorizer:
type: COGNITO_USER_POOLS
authorizerId: <authorizer_id>
provider:
name: aws
versionFunctions: false
runtime: nodejs14.x
stage: development
region: eu-west-1
role: <role>
timeout: 30
apiGateway:
restApiId: <rest_api_id>
restApiRootResourceId: <rest_api_root_resource_id>
functions:
createCompany:
handler: src/company/create-company.handler
events:
- http:
<<: *http
path: /company/create
method: post
getCompany:
handler: src/company/get-company.handler
events:
- http:
<<: *http
path: company/get
method: get
This is a simple configuration file for defining 2 lambdas: one for creating and another for getting a company. Let’s understand each line.
custom:
http: &http
cors: true
authorizer:
type: COGNITO_USER_POOLS
authorizerId: <authorizer_id>
Here we define a yml variable to not repeat ourselves.
The &http variable will contain the configuration for referencing the API Gateway authorizer and handle cors.
You see it reused throughout the code using <<: *http which inserts the code defined above under each key definition.
apiGateway:
restApiId: <rest_api_id>
restApiRootResourceId: <rest_api_root_resource_id>
This is the api gateway configuration.
You can either create it using serverless or another infrastructure as code tool that gives you more freedom.
I personally prefer Pulumi and import the configuration using a custom file. I’ll share more tutorials on this topic in the following articles.
functions:
createCompany:
handler: src/company/create-company.handler
events:
- http:
<<: *http
path: company/create
method: post
getCompany:
handler: src/company/get-company.handler
events:
- http:
<<: *http
path: company/get
method: post
Here we define 2 lambdas for:
- creating the company
- getting the company
Defining the lambda takes a few arguments, the most important ones being events.path and handler. Under handler it takes a path to a <filename>.<exported function> (above src/company/get-company file exports handler function e.g. export const handler = () => {}).
How do I add Typescript support ?
Either you are migrating your project or just starting out from scratch, the same configuration applies.
The key components that need to be added in the configuration are the following 2 plugins:
plugins:
- serverless-plugin-typescript
- serverless-plugin-optimize
After you added them in your configuration file above, make sure to install them using yarn or npm.
yarn add serverless-plugin-typescript --dev
yarn add serverless-plugin-optimize --dev
OR
npm install serverless-plugin-typescript --dev
npm install serverless-plugin-optimize --dev
Our final configuration file will look like this:
service: company
custom:
http: &http
cors: true
authorizer:
type: COGNITO_USER_POOLS
authorizerId: <authorizer_id>
plugins:
- serverless-plugin-typescript
- serverless-plugin-optimize
provider:
name: aws
versionFunctions: false
runtime: nodejs14.x
stage: development
region: eu-west-1
role: <role>
timeout: 30
apiGateway:
restApiId: <rest_api_id>
restApiRootResourceId: <rest_api_root_resource_id>
functions:
createCompany:
handler: src/company/create-company.handler
events:
- http:
<<: *http
path: company/create
method: post
getCompany:
handler: src/company/get-company.handler
events:
- http:
<<: *http
path: company/get
method: post
I hope you learned something new. If you are interested in more, please check the previous post on Linux: How to get started?